| 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_CLANG |
| 232 | test_is_not_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 | |