1 | //===----------------------------------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | // type_traits |
10 | |
11 | // template <class T, class... Args> |
12 | // struct is_constructible; |
13 | |
14 | #include <type_traits> |
15 | #include "test_macros.h" |
16 | |
17 | struct A |
18 | { |
19 | explicit A(int); |
20 | A(int, double); |
21 | A(int, long, double); |
22 | #if TEST_STD_VER >= 11 |
23 | private: |
24 | #endif |
25 | A(char); |
26 | }; |
27 | |
28 | struct Base {}; |
29 | struct Derived : public Base {}; |
30 | |
31 | class Abstract |
32 | { |
33 | virtual void foo() = 0; |
34 | }; |
35 | |
36 | class AbstractDestructor |
37 | { |
38 | virtual ~AbstractDestructor() = 0; |
39 | }; |
40 | |
41 | struct PrivateDtor { |
42 | PrivateDtor(int) {} |
43 | private: |
44 | ~PrivateDtor() {} |
45 | }; |
46 | |
47 | struct S { |
48 | template <class T> |
49 | #if TEST_STD_VER >= 11 |
50 | explicit |
51 | #endif |
52 | operator T () const; |
53 | }; |
54 | |
55 | template <class To> |
56 | struct ImplicitTo { |
57 | operator To(); |
58 | }; |
59 | |
60 | #if TEST_STD_VER >= 11 |
61 | template <class To> |
62 | struct ExplicitTo { |
63 | explicit operator To (); |
64 | }; |
65 | #endif |
66 | |
67 | |
68 | template <class T> |
69 | void test_is_constructible() |
70 | { |
71 | static_assert( (std::is_constructible<T>::value), "" ); |
72 | #if TEST_STD_VER > 14 |
73 | static_assert( std::is_constructible_v<T>, "" ); |
74 | #endif |
75 | } |
76 | |
77 | template <class T, class A0> |
78 | void test_is_constructible() |
79 | { |
80 | static_assert(( std::is_constructible<T, A0>::value), "" ); |
81 | #if TEST_STD_VER > 14 |
82 | static_assert(( std::is_constructible_v<T, A0>), "" ); |
83 | #endif |
84 | } |
85 | |
86 | template <class T, class A0, class A1> |
87 | void test_is_constructible() |
88 | { |
89 | static_assert(( std::is_constructible<T, A0, A1>::value), "" ); |
90 | #if TEST_STD_VER > 14 |
91 | static_assert(( std::is_constructible_v<T, A0, A1>), "" ); |
92 | #endif |
93 | } |
94 | |
95 | template <class T, class A0, class A1, class A2> |
96 | void test_is_constructible() |
97 | { |
98 | static_assert(( std::is_constructible<T, A0, A1, A2>::value), "" ); |
99 | #if TEST_STD_VER > 14 |
100 | static_assert(( std::is_constructible_v<T, A0, A1, A2>), "" ); |
101 | #endif |
102 | } |
103 | |
104 | template <class T> |
105 | void test_is_not_constructible() |
106 | { |
107 | static_assert((!std::is_constructible<T>::value), "" ); |
108 | #if TEST_STD_VER > 14 |
109 | static_assert((!std::is_constructible_v<T>), "" ); |
110 | #endif |
111 | } |
112 | |
113 | template <class T, class A0> |
114 | void test_is_not_constructible() |
115 | { |
116 | static_assert((!std::is_constructible<T, A0>::value), "" ); |
117 | #if TEST_STD_VER > 14 |
118 | static_assert((!std::is_constructible_v<T, A0>), "" ); |
119 | #endif |
120 | } |
121 | |
122 | int main(int, char**) |
123 | { |
124 | typedef Base B; |
125 | typedef Derived D; |
126 | |
127 | test_is_constructible<int> (); |
128 | test_is_constructible<int, const int> (); |
129 | test_is_constructible<A, int> (); |
130 | test_is_constructible<A, int, double> (); |
131 | test_is_constructible<A, int, long, double> (); |
132 | test_is_constructible<int&, int&> (); |
133 | |
134 | test_is_not_constructible<A> (); |
135 | #if TEST_STD_VER >= 11 |
136 | test_is_not_constructible<A, char> (); |
137 | #else |
138 | test_is_constructible<A, char> (); |
139 | #endif |
140 | test_is_not_constructible<A, void> (); |
141 | test_is_not_constructible<int, void()>(); |
142 | test_is_not_constructible<int, void(&)()>(); |
143 | test_is_not_constructible<int, void() const>(); |
144 | test_is_not_constructible<int&, void>(); |
145 | test_is_not_constructible<int&, void()>(); |
146 | test_is_not_constructible<int&, void() const>(); |
147 | test_is_not_constructible<int&, void(&)()>(); |
148 | |
149 | test_is_not_constructible<void> (); |
150 | test_is_not_constructible<const void> (); // LWG 2738 |
151 | test_is_not_constructible<volatile void> (); |
152 | test_is_not_constructible<const volatile void> (); |
153 | test_is_not_constructible<int&> (); |
154 | test_is_not_constructible<Abstract> (); |
155 | test_is_not_constructible<AbstractDestructor> (); |
156 | test_is_constructible<int, S>(); |
157 | test_is_not_constructible<int&, S>(); |
158 | |
159 | test_is_constructible<void(&)(), void(&)()>(); |
160 | test_is_constructible<void(&)(), void()>(); |
161 | #if TEST_STD_VER >= 11 |
162 | test_is_constructible<void(&&)(), void(&&)()>(); |
163 | test_is_constructible<void(&&)(), void()>(); |
164 | test_is_constructible<void(&&)(), void(&)()>(); |
165 | #endif |
166 | |
167 | #if TEST_STD_VER >= 11 |
168 | test_is_constructible<int const&, int>(); |
169 | test_is_constructible<int const&, int&&>(); |
170 | |
171 | test_is_constructible<int&&, double&>(); |
172 | test_is_constructible<void(&)(), void(&&)()>(); |
173 | |
174 | test_is_not_constructible<int&, int>(); |
175 | test_is_not_constructible<int&, int const&>(); |
176 | test_is_not_constructible<int&, int&&>(); |
177 | |
178 | test_is_constructible<int&&, int>(); |
179 | test_is_constructible<int&&, int&&>(); |
180 | test_is_not_constructible<int&&, int&>(); |
181 | test_is_not_constructible<int&&, int const&&>(); |
182 | |
183 | test_is_constructible<Base, Derived>(); |
184 | test_is_constructible<Base&, Derived&>(); |
185 | test_is_not_constructible<Derived&, Base&>(); |
186 | test_is_constructible<Base const&, Derived const&>(); |
187 | #ifndef TEST_COMPILER_GCC |
188 | test_is_not_constructible<Derived const&, Base const&>(); |
189 | test_is_not_constructible<Derived const&, Base>(); |
190 | #endif |
191 | |
192 | test_is_constructible<Base&&, Derived>(); |
193 | test_is_constructible<Base&&, Derived&&>(); |
194 | #ifndef TEST_COMPILER_GCC |
195 | test_is_not_constructible<Derived&&, Base&&>(); |
196 | test_is_not_constructible<Derived&&, Base>(); |
197 | #endif |
198 | |
199 | // test that T must also be destructible |
200 | test_is_constructible<PrivateDtor&, PrivateDtor&>(); |
201 | test_is_not_constructible<PrivateDtor, int>(); |
202 | |
203 | test_is_not_constructible<void() const, void() const>(); |
204 | test_is_not_constructible<void() const, void*>(); |
205 | |
206 | test_is_constructible<int&, ImplicitTo<int&>>(); |
207 | test_is_constructible<const int&, ImplicitTo<int&&>>(); |
208 | test_is_constructible<int&&, ImplicitTo<int&&>>(); |
209 | test_is_constructible<const int&, ImplicitTo<int>>(); |
210 | |
211 | test_is_not_constructible<B&&, B&>(); |
212 | test_is_not_constructible<B&&, D&>(); |
213 | test_is_constructible<B&&, ImplicitTo<D&&>>(); |
214 | test_is_constructible<B&&, ImplicitTo<D&&>&>(); |
215 | test_is_constructible<int&&, double&>(); |
216 | test_is_constructible<const int&, ImplicitTo<int&>&>(); |
217 | test_is_constructible<const int&, ImplicitTo<int&>>(); |
218 | test_is_constructible<const int&, ExplicitTo<int&>&>(); |
219 | test_is_constructible<const int&, ExplicitTo<int&>>(); |
220 | |
221 | test_is_constructible<const int&, ExplicitTo<int&>&>(); |
222 | test_is_constructible<const int&, ExplicitTo<int&>>(); |
223 | |
224 | |
225 | // Binding through reference-compatible type is required to perform |
226 | // direct-initialization as described in [over.match.ref] p. 1 b. 1: |
227 | // |
228 | // But the rvalue to lvalue reference binding isn't allowed according to |
229 | // [over.match.ref] despite Clang accepting it. |
230 | test_is_constructible<int&, ExplicitTo<int&>>(); |
231 | #ifndef TEST_COMPILER_GCC |
232 | test_is_constructible<const int&, ExplicitTo<int&&>>(); |
233 | #endif |
234 | |
235 | static_assert(std::is_constructible<int&&, ExplicitTo<int&&>>::value, "" ); |
236 | |
237 | #ifdef __clang__ |
238 | // FIXME Clang and GCC disagree on the validity of this expression. |
239 | test_is_constructible<const int&, ExplicitTo<int>>(); |
240 | static_assert(std::is_constructible<int&&, ExplicitTo<int>>::value, "" ); |
241 | #else |
242 | test_is_not_constructible<const int&, ExplicitTo<int>>(); |
243 | test_is_not_constructible<int&&, ExplicitTo<int>>(); |
244 | #endif |
245 | |
246 | // Binding through temporary behaves like copy-initialization, |
247 | // see [dcl.init.ref] p. 5, very last sub-bullet: |
248 | test_is_not_constructible<const int&, ExplicitTo<double&&>>(); |
249 | test_is_not_constructible<int&&, ExplicitTo<double&&>>(); |
250 | |
251 | test_is_not_constructible<void()>(); |
252 | test_is_not_constructible<void() const> (); |
253 | test_is_not_constructible<void() volatile> (); |
254 | test_is_not_constructible<void() &> (); |
255 | test_is_not_constructible<void() &&> (); |
256 | #endif // TEST_STD_VER >= 11 |
257 | |
258 | return 0; |
259 | } |
260 | |