Author: ericwf Date: Wed Jul 20 00:01:24 2016 New Revision: 276084 URL: http://llvm.org/viewvc/llvm-project?rev=276084&view=rev Log: Reimplement is_constructible fallback implementation. Fixes PR21574.
The previous implementation relied highly on specializations to handle special cases. This new implementation lets the compiler do the work when possible. Modified: libcxx/trunk/include/type_traits libcxx/trunk/test/std/utilities/meta/meta.unary/meta.unary.prop/is_constructible.pass.cpp libcxx/trunk/test/std/utilities/meta/meta.unary/meta.unary.prop/is_default_constructible.pass.cpp Modified: libcxx/trunk/include/type_traits URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/type_traits?rev=276084&r1=276083&r2=276084&view=diff ============================================================================== --- libcxx/trunk/include/type_traits (original) +++ libcxx/trunk/include/type_traits Wed Jul 20 00:01:24 2016 @@ -2913,119 +2913,75 @@ struct _LIBCPP_TYPE_VIS_ONLY is_construc // main is_constructible test -template <class _Tp, class ..._Args> -typename __select_2nd<decltype(_VSTD::move(_Tp(_VSTD::declval<_Args>()...))), true_type>::type -__is_constructible_test(_Tp&&, _Args&& ...); - -template <class ..._Args> -false_type -__is_constructible_test(__any, _Args&& ...); - -template <bool, class _Tp, class... _Args> -struct __libcpp_is_constructible // false, _Tp is not a scalar - : public common_type - < - decltype(__is_constructible_test(declval<_Tp>(), declval<_Args>()...)) - >::type - {}; - -// function types are not constructible - -template <class _Rp, class... _A1, class... _A2> -struct __libcpp_is_constructible<false, _Rp(_A1...), _A2...> - : public false_type - {}; -// handle scalars and reference types +struct __is_constructible_helper +{ + template <class _Tp> + static true_type __test_ref(_Tp); + template <class> + static false_type __test_ref(...); + + template <class _Tp, class ..._Args, + class = decltype(_Tp(_VSTD::declval<_Args>()...))> + static true_type __test_nary(int); + template <class _Tp, class...> + static false_type __test_nary(...); + + template <class _Tp, class _A0, class = decltype(::new _Tp(_VSTD::declval<_A0>()))> + static is_destructible<_Tp> __test_unary(int); + template <class, class> + static false_type __test_unary(...); +}; -// Scalars are default constructible, references are not +template <class _Tp, bool = is_void<_Tp>::value> +struct __is_default_constructible + : decltype(__is_constructible_helper::__test_nary<_Tp>(0)) +{}; template <class _Tp> -struct __libcpp_is_constructible<true, _Tp> - : public is_scalar<_Tp> - {}; - -// Scalars and references are constructible from one arg if that arg is -// implicitly convertible to the scalar or reference. +struct __is_default_constructible<_Tp, true> : false_type {}; template <class _Tp> -struct __is_constructible_ref -{ - true_type static __lxx(_Tp); - false_type static __lxx(...); -}; +struct __is_default_constructible<_Tp[], false> : false_type {}; -template <class _Tp, class _A0> -struct __libcpp_is_constructible<true, _Tp, _A0> - : public common_type - < - decltype(__is_constructible_ref<_Tp>::__lxx(declval<_A0>())) - >::type - {}; - -// Scalars and references are not constructible from multiple args. - -template <class _Tp, class _A0, class ..._Args> -struct __libcpp_is_constructible<true, _Tp, _A0, _Args...> - : public false_type - {}; - -// Treat scalars and reference types separately - -template <bool, class _Tp, class... _Args> -struct __is_constructible_void_check - : public __libcpp_is_constructible<is_scalar<_Tp>::value || is_reference<_Tp>::value, - _Tp, _Args...> - {}; - -// If any of T or Args is void, is_constructible should be false +template <class _Tp, size_t _Nx> +struct __is_default_constructible<_Tp[_Nx], false> + : __is_default_constructible<typename remove_all_extents<_Tp>::type> {}; template <class _Tp, class... _Args> -struct __is_constructible_void_check<true, _Tp, _Args...> - : public false_type - {}; +struct __libcpp_is_constructible +{ + static_assert(sizeof...(_Args) > 1, "Wrong specialization"); + typedef decltype(__is_constructible_helper::__test_nary<_Tp, _Args...>(0)) + type; +}; -template <class ..._Args> struct __contains_void; +template <class _Tp> +struct __libcpp_is_constructible<_Tp> : __is_default_constructible<_Tp> {}; -template <> struct __contains_void<> : false_type {}; +template <class _Tp, class _A0> +struct __libcpp_is_constructible<_Tp, _A0> + : public decltype(__is_constructible_helper::__test_unary<_Tp, _A0>(0)) +{}; -template <class _A0, class ..._Args> -struct __contains_void<_A0, _Args...> -{ - static const bool value = is_void<_A0>::value || - __contains_void<_Args...>::value; -}; +template <class _Tp, class _A0> +struct __libcpp_is_constructible<_Tp&, _A0> + : public decltype(__is_constructible_helper:: + __test_ref<_Tp&>(_VSTD::declval<_A0>())) +{}; + +template <class _Tp, class _A0> +struct __libcpp_is_constructible<_Tp&&, _A0> + : public decltype(__is_constructible_helper:: + __test_ref<_Tp&&>(_VSTD::declval<_A0>())) +{}; // is_constructible entry point template <class _Tp, class... _Args> struct _LIBCPP_TYPE_VIS_ONLY is_constructible - : public __is_constructible_void_check<__contains_void<_Tp, _Args...>::value - || is_abstract<_Tp>::value, - _Tp, _Args...> - {}; - -// Array types are default constructible if their element type -// is default constructible - -template <class _Ap, size_t _Np> -struct __libcpp_is_constructible<false, _Ap[_Np]> - : public is_constructible<typename remove_all_extents<_Ap>::type> - {}; - -// Otherwise array types are not constructible by this syntax - -template <class _Ap, size_t _Np, class ..._Args> -struct __libcpp_is_constructible<false, _Ap[_Np], _Args...> - : public false_type - {}; - -// Incomplete array types are not constructible - -template <class _Ap, class ..._Args> -struct __libcpp_is_constructible<false, _Ap[], _Args...> - : public false_type - {}; + : public __libcpp_is_constructible<_Tp, _Args...>::type {}; + #else // _LIBCPP_HAS_NO_VARIADICS Modified: libcxx/trunk/test/std/utilities/meta/meta.unary/meta.unary.prop/is_constructible.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/meta/meta.unary/meta.unary.prop/is_constructible.pass.cpp?rev=276084&r1=276083&r2=276084&view=diff ============================================================================== --- libcxx/trunk/test/std/utilities/meta/meta.unary/meta.unary.prop/is_constructible.pass.cpp (original) +++ libcxx/trunk/test/std/utilities/meta/meta.unary/meta.unary.prop/is_constructible.pass.cpp Wed Jul 20 00:01:24 2016 @@ -27,6 +27,9 @@ private: A(char); }; +struct Base {}; +struct Derived : public Base {}; + class Abstract { virtual void foo() = 0; @@ -37,6 +40,21 @@ class AbstractDestructor virtual ~AbstractDestructor() = 0; }; +struct PrivateDtor { + PrivateDtor(int) {} +private: + ~PrivateDtor() {} +}; + +struct S { + template <class T> +#if TEST_STD_VER >= 11 + explicit +#endif + operator T () const { return T(); } +}; + + template <class T> void test_is_constructible() { @@ -101,13 +119,41 @@ int main() test_is_not_constructible<int&> (); test_is_not_constructible<Abstract> (); test_is_not_constructible<AbstractDestructor> (); + test_is_constructible<int, S>(); + test_is_not_constructible<int&, S>(); + +#if TEST_STD_VER >= 11 + test_is_constructible<int const&, int>(); + test_is_constructible<int const&, int&&>(); -// LWG 2560 -- postpone this test until bots updated -// test_is_not_constructible<void()> (); -#if TEST_STD_VER > 11 -// test_is_not_constructible<void() const> (); -// test_is_not_constructible<void() volatile> (); -// test_is_not_constructible<void() &> (); -// test_is_not_constructible<void() &&> (); + test_is_not_constructible<int&, int>(); + test_is_not_constructible<int&, int const&>(); + test_is_not_constructible<int&, int&&>(); + + test_is_constructible<int&&, int>(); + test_is_constructible<int&&, int&&>(); + test_is_not_constructible<int&&, int&>(); + test_is_not_constructible<int&&, int const&&>(); + + test_is_constructible<Base, Derived>(); + test_is_constructible<Base&, Derived&>(); + test_is_not_constructible<Derived&, Base&>(); + test_is_constructible<Base const&, Derived const&>(); + test_is_not_constructible<Derived const&, Base const&>(); + test_is_not_constructible<Derived const&, Base>(); + + test_is_constructible<Base&&, Derived>(); + test_is_constructible<Base&&, Derived&&>(); + test_is_not_constructible<Derived&&, Base&&>(); + test_is_not_constructible<Derived&&, Base>(); + + // test that T must also be destructible + test_is_constructible<PrivateDtor&, PrivateDtor&>(); + test_is_not_constructible<PrivateDtor, int>(); + + test_is_not_constructible<void() const> (); + test_is_not_constructible<void() volatile> (); + test_is_not_constructible<void() &> (); + test_is_not_constructible<void() &&> (); #endif } Modified: libcxx/trunk/test/std/utilities/meta/meta.unary/meta.unary.prop/is_default_constructible.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/meta/meta.unary/meta.unary.prop/is_default_constructible.pass.cpp?rev=276084&r1=276083&r2=276084&view=diff ============================================================================== --- libcxx/trunk/test/std/utilities/meta/meta.unary/meta.unary.prop/is_default_constructible.pass.cpp (original) +++ libcxx/trunk/test/std/utilities/meta/meta.unary/meta.unary.prop/is_default_constructible.pass.cpp Wed Jul 20 00:01:24 2016 @@ -92,15 +92,22 @@ int main() test_is_default_constructible<int*>(); test_is_default_constructible<const int*>(); test_is_default_constructible<char[3]>(); + test_is_default_constructible<char[5][3]>(); + test_is_default_constructible<NotEmpty>(); test_is_default_constructible<bit_zero>(); test_is_not_default_constructible<void>(); test_is_not_default_constructible<int&>(); test_is_not_default_constructible<char[]>(); + test_is_not_default_constructible<char[][3]>(); + test_is_not_default_constructible<Abstract>(); test_is_not_default_constructible<NoDefaultConstructor>(); #if TEST_STD_VER >= 11 test_is_not_default_constructible<B>(); + test_is_not_default_constructible<int&&>(); + test_is_not_default_constructible<void()>(); + test_is_not_default_constructible<void() const>(); #endif } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits