diff options
Diffstat (limited to 'libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_constructible.pass.cpp')
| -rw-r--r-- | libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_constructible.pass.cpp | 120 |
1 files changed, 118 insertions, 2 deletions
diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_constructible.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_constructible.pass.cpp index 7f5ab7214fd..eb942a52a5b 100644 --- a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_constructible.pass.cpp +++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_constructible.pass.cpp @@ -14,9 +14,17 @@ // template <class T, class... Args> // struct is_constructible; +#define _LIBCPP_TESTING_FALLBACK_IS_CONSTRUCTIBLE #include <type_traits> #include "test_macros.h" +#if TEST_STD_VER >= 11 && defined(_LIBCPP_VERSION) +#define LIBCPP11_STATIC_ASSERT(...) static_assert(__VA_ARGS__) +#else +#define LIBCPP11_STATIC_ASSERT(...) ((void)0) +#endif + + struct A { explicit A(int); @@ -51,14 +59,27 @@ struct S { #if TEST_STD_VER >= 11 explicit #endif - operator T () const { return T(); } + operator T () const; +}; + +template <class To> +struct ImplicitTo { + operator To(); +}; + +#if TEST_STD_VER >= 11 +template <class To> +struct ExplicitTo { + explicit operator To (); }; +#endif template <class T> void test_is_constructible() { static_assert( (std::is_constructible<T>::value), ""); + LIBCPP11_STATIC_ASSERT((std::__libcpp_is_constructible<T>::type::value), ""); #if TEST_STD_VER > 14 static_assert( std::is_constructible_v<T>, ""); #endif @@ -68,6 +89,7 @@ template <class T, class A0> void test_is_constructible() { static_assert(( std::is_constructible<T, A0>::value), ""); + LIBCPP11_STATIC_ASSERT((std::__libcpp_is_constructible<T, A0>::type::value), ""); #if TEST_STD_VER > 14 static_assert(( std::is_constructible_v<T, A0>), ""); #endif @@ -77,6 +99,7 @@ template <class T, class A0, class A1> void test_is_constructible() { static_assert(( std::is_constructible<T, A0, A1>::value), ""); + LIBCPP11_STATIC_ASSERT((std::__libcpp_is_constructible<T, A0, A1>::type::value), ""); #if TEST_STD_VER > 14 static_assert(( std::is_constructible_v<T, A0, A1>), ""); #endif @@ -86,6 +109,7 @@ template <class T> void test_is_not_constructible() { static_assert((!std::is_constructible<T>::value), ""); + LIBCPP11_STATIC_ASSERT((!std::__libcpp_is_constructible<T>::type::value), ""); #if TEST_STD_VER > 14 static_assert((!std::is_constructible_v<T>), ""); #endif @@ -95,13 +119,28 @@ template <class T, class A0> void test_is_not_constructible() { static_assert((!std::is_constructible<T, A0>::value), ""); + LIBCPP11_STATIC_ASSERT((!std::__libcpp_is_constructible<T, A0>::type::value), ""); #if TEST_STD_VER > 14 static_assert((!std::is_constructible_v<T, A0>), ""); #endif } +#if TEST_STD_VER >= 11 +template <class T = int, class = decltype(static_cast<T&&>(std::declval<double&>()))> +constexpr bool clang_disallows_valid_static_cast_test(int) { return false; }; + +constexpr bool clang_disallows_valid_static_cast_test(long) { return true; } + +static constexpr bool clang_disallows_valid_static_cast_bug = + clang_disallows_valid_static_cast_test(0); +#endif + + int main() { + typedef Base B; + typedef Derived D; + test_is_constructible<int> (); test_is_constructible<int, const int> (); test_is_constructible<A, int> (); @@ -115,6 +154,14 @@ int main() test_is_constructible<A, char> (); #endif test_is_not_constructible<A, void> (); + test_is_not_constructible<int, void()>(); + test_is_not_constructible<int, void(&)()>(); + test_is_not_constructible<int, void() const>(); + test_is_not_constructible<int&, void>(); + test_is_not_constructible<int&, void()>(); + test_is_not_constructible<int&, void() const>(); + test_is_not_constructible<int&, void(&)()>(); + test_is_not_constructible<void> (); test_is_not_constructible<const void> (); // LWG 2738 test_is_not_constructible<volatile void> (); @@ -125,10 +172,21 @@ int main() test_is_constructible<int, S>(); test_is_not_constructible<int&, S>(); + test_is_constructible<void(&)(), void(&)()>(); + test_is_constructible<void(&)(), void()>(); +#if TEST_STD_VER >= 11 + test_is_constructible<void(&&)(), void(&&)()>(); + test_is_constructible<void(&&)(), void()>(); + test_is_constructible<void(&&)(), void(&)()>(); +#endif + #if TEST_STD_VER >= 11 test_is_constructible<int const&, int>(); test_is_constructible<int const&, int&&>(); + test_is_constructible<int&&, double&>(); + test_is_constructible<void(&)(), void(&&)()>(); + test_is_not_constructible<int&, int>(); test_is_not_constructible<int&, int const&>(); test_is_not_constructible<int&, int&&>(); @@ -157,6 +215,64 @@ int main() test_is_not_constructible<void() const, void() const>(); test_is_not_constructible<void() const, void*>(); + test_is_constructible<int&, ImplicitTo<int&>>(); + test_is_constructible<const int&, ImplicitTo<int&&>>(); + test_is_constructible<int&&, ImplicitTo<int&&>>(); + test_is_constructible<const int&, ImplicitTo<int>>(); + + test_is_not_constructible<B&&, B&>(); + test_is_not_constructible<B&&, D&>(); + test_is_constructible<B&&, ImplicitTo<D&&>>(); + test_is_constructible<B&&, ImplicitTo<D&&>&>(); + test_is_constructible<int&&, double&>(); + test_is_constructible<const int&, ImplicitTo<int&>&>(); + test_is_constructible<const int&, ImplicitTo<int&>>(); + test_is_constructible<const int&, ExplicitTo<int&>&>(); + test_is_constructible<const int&, ExplicitTo<int&>>(); + + test_is_constructible<const int&, ExplicitTo<int&>&>(); + test_is_constructible<const int&, ExplicitTo<int&>>(); + test_is_constructible<int&, ExplicitTo<int&>>(); + test_is_constructible<const int&, ExplicitTo<int&&>>(); + + // Binding through reference-compatible type is required to perform + // direct-initialization as described in [over.match.ref] p. 1 b. 1: + test_is_constructible<int&, ExplicitTo<int&>>(); + test_is_constructible<const int&, ExplicitTo<int&&>>(); + + static_assert(std::is_constructible<int&&, ExplicitTo<int&&>>::value, ""); +#ifdef __clang__ +#if defined(CLANG_TEST_VER) && CLANG_TEST_VER < 400 + static_assert(clang_disallows_valid_static_cast_bug, "bug still exists"); +#endif + // FIXME Clang disallows this construction because it thinks that + // 'static_cast<int&&>(declval<ExplicitTo<int&&>>())' is ill-formed. + LIBCPP_STATIC_ASSERT( + clang_disallows_valid_static_cast_bug != + std::__libcpp_is_constructible<int&&, ExplicitTo<int&&>>::value, ""); +#else + static_assert(clang_disallows_valid_static_cast_bug == false, ""); + LIBCPP_STATIC_ASSERT(std::__libcpp_is_constructible<int&&, ExplicitTo<int&&>>::value, ""); +#endif + +#ifdef __clang__ + // FIXME Clang and GCC disagree on the validity of this expression. + test_is_constructible<const int&, ExplicitTo<int>>(); + static_assert(std::is_constructible<int&&, ExplicitTo<int>>::value, ""); + LIBCPP_STATIC_ASSERT( + clang_disallows_valid_static_cast_bug != + std::__libcpp_is_constructible<int&&, ExplicitTo<int>>::value, ""); +#else + test_is_not_constructible<const int&, ExplicitTo<int>>(); + test_is_not_constructible<int&&, ExplicitTo<int>>(); +#endif + + // Binding through temporary behaves like copy-initialization, + // see [dcl.init.ref] p. 5, very last sub-bullet: + test_is_not_constructible<const int&, ExplicitTo<double&&>>(); + test_is_not_constructible<int&&, ExplicitTo<double&&>>(); + + // TODO: Remove this workaround once Clang <= 3.7 are no longer used regularly. // In those compiler versions the __is_constructible builtin gives the wrong // results for abominable function types. @@ -171,5 +287,5 @@ int main() test_is_not_constructible<void() &> (); test_is_not_constructible<void() &&> (); #endif -#endif +#endif // TEST_STD_VER >= 11 } |

