[libcxx] r276084 - Reimplement is_constructible fallback implementation. Fixes PR21574.
Eric Fiselier via cfe-commits
cfe-commits at lists.llvm.org
Tue Jul 19 22:01:25 PDT 2016
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
}
More information about the cfe-commits
mailing list