From 2c7a09d774a2af28c51224404ba47f5f7c182cea Mon Sep 17 00:00:00 2001 From: Paolo Carlini Date: Sat, 30 Apr 2011 19:40:06 +0000 Subject: [PATCH] [multiple changes] 2011-04-30 Daniel Krugler * include/std/type_traits (__is_default_constructible_atom, __is_default_constructible_safe<, true>, __is_direct_constructible_new_safe, __is_base_to_derived_ref<,, true>, __is_lvalue_to_rvalue_ref<,, true>, __is_direct_constructible_ref_cast, __is_direct_constructible, __is_nary_constructible): Simplify; add comments throughout. 2011-04-30 Paolo Carlini * testsuite/20_util/make_signed/requirements/typedefs_neg.cc: Adjust dg-error line numbers. * testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc: Likewise. * testsuite/20_util/declval/requirements/1_neg.cc: Likewise. From-SVN: r173222 --- libstdc++-v3/ChangeLog | 17 ++++ libstdc++-v3/include/std/type_traits | 84 +++++++++++-------- .../20_util/declval/requirements/1_neg.cc | 2 +- .../make_signed/requirements/typedefs_neg.cc | 4 +- .../requirements/typedefs_neg.cc | 4 +- 5 files changed, 70 insertions(+), 41 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 5dfeb777dcb..8e509aa7500 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,20 @@ +2011-04-30 Daniel Krugler + + * include/std/type_traits (__is_default_constructible_atom, + __is_default_constructible_safe<, true>, + __is_direct_constructible_new_safe, + __is_base_to_derived_ref<,, true>, __is_lvalue_to_rvalue_ref<,, true>, + __is_direct_constructible_ref_cast, __is_direct_constructible, + __is_nary_constructible): Simplify; add comments throughout. + +2011-04-30 Paolo Carlini + + * testsuite/20_util/make_signed/requirements/typedefs_neg.cc: + Adjust dg-error line numbers. + * testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc: + Likewise. + * testsuite/20_util/declval/requirements/1_neg.cc: Likewise. + 2011-04-30 Doug Kwan * include/Makefile.am (install-freestanding-headers): Also install diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index 6d33416c330..0560522cbfd 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -550,7 +550,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct __is_array_unknown_bounds : public __and_, __not_>>::type { }; - + + // In N3290 is_destructible does not say anything about function + // types and abstract types, see LWG 2049. This implementation + // describes function types as trivially nothrow destructible and + // abstract types as destructible, iff the explicit destructor + // call expression is wellformed. struct __do_is_destructible_impl_1 { template @@ -571,6 +576,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef decltype(__test<_Tp>(0)) type; }; + // Special implementation for abstract types struct __do_is_destructible_impl_2 { template().~_Tp())> @@ -632,23 +638,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template struct __is_default_constructible_atom - : public __and_, - __is_default_constructible_impl<_Tp>>::type::type + : public __and_<__not_>, + __is_default_constructible_impl<_Tp>>::type { }; template::value> struct __is_default_constructible_safe; - // The following technique is a workaround for a gcc defect, which does - // not sfinae away attempts to default-construct arrays of unknown bounds. - // Complete arrays can be default-constructed, if the element type is - // default-constructible, but arrays with unknown bounds are not: - + // The following technique is a workaround for a current core language + // restriction, which does not allow for array types to occur in + // functional casts of the form T(). Complete arrays can be default- + // constructed, if the element type is default-constructible, but + // arrays with unknown bounds are not. template struct __is_default_constructible_safe<_Tp, true> : public __and_<__is_array_known_bounds<_Tp>, __is_default_constructible_atom::type>>::type::type + remove_all_extents<_Tp>::type>>::type { }; template @@ -663,6 +669,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Tp>::value)> { }; + + // Implementation of is_constructible. + + // The hardest part of this trait is the binary direct-initialization + // case, because we hit into a functional cast of the form T(arg). + // This implementation uses different strategies depending on the + // target type to reduce the test overhead as much as possible: + // + // a) For a reference target type, we use a static_cast expression + // modulo its extra cases. + // + // b) For a non-reference target type we use a ::new expression. struct __do_is_static_castable_impl { template struct __is_static_castable_safe - : public __and_<__or_, is_destructible<_To>>, - __is_static_castable_impl<_From, _To>>::type::type + : public __is_static_castable_impl<_From, _To>::type { }; // __is_static_castable @@ -693,6 +710,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _From, _To>::value)> { }; + // Implementation for non-reference types. To meet the proper + // variable definition semantics, we also need to test for + // is_destructible in this case. struct __do_is_direct_constructible_impl { template struct __is_direct_constructible_new_safe : public __and_, - __is_direct_constructible_impl<_Tp, _Arg>>::type::type + __is_direct_constructible_impl<_Tp, _Arg>>::type { }; template @@ -736,10 +756,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >::type>::type __src_t; typedef typename remove_cv::type>::type __dst_t; - typedef typename __and_< - __not_>, - is_base_of<__src_t, __dst_t> - >::type type; + typedef __and_<__not_>, + is_base_of<__src_t, __dst_t>> type; static constexpr bool value = type::value; }; @@ -760,10 +778,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _From>::type>::type __src_t; typedef typename remove_cv::type>::type __dst_t; - typedef typename __or_< - is_same<__src_t, __dst_t>, - is_base_of<__dst_t, __src_t> - >::type type; + typedef __or_, + is_base_of<__dst_t, __src_t>> type; static constexpr bool value = type::value; }; @@ -772,25 +788,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public false_type { }; - // Here we handle direct-initialization to a reference type - // as equivalent to a static_cast modulo overshooting conversions. - // These are restricted to the following conversion: - // a) A base class to a derived class reference - // b) An lvalue-reference to an rvalue-reference - + // Here we handle direct-initialization to a reference type as + // equivalent to a static_cast modulo overshooting conversions. + // These are restricted to the following conversions: + // a) A glvalue of a base class to a derived class reference + // b) An lvalue to an rvalue-reference of reference-compatible + // types template struct __is_direct_constructible_ref_cast : public __and_<__is_static_castable<_Arg, _Tp>, __not_<__or_<__is_base_to_derived_ref<_Arg, _Tp>, __is_lvalue_to_rvalue_ref<_Arg, _Tp> - >>>::type::type + >>>::type { }; - // Direct-initialization is tricky, because of functional - // casts: For a conversion to reference we fall back to a - // static_cast modulo extra cases, otherwise we use a - // new expression: - template struct __is_direct_constructible_new : public conditional::value, @@ -802,9 +813,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template struct __is_direct_constructible : public integral_constant::type::value)> + _Tp, _Arg>::value)> { }; + // Since default-construction and binary direct-initialization have + // been handled separately, the implementation of the remaining + // n-ary construction cases is rather straightforward. struct __do_is_nary_constructible_impl { template struct __is_nary_constructible - : public __and_, - __is_nary_constructible_impl<_Tp, _Args...> - >::type::type + : public __is_nary_constructible_impl<_Tp, _Args...>::type { static_assert(sizeof...(_Args) > 1, "Only useful for > 1 arguments"); diff --git a/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc b/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc index af1522b7a40..4fa005ecdd6 100644 --- a/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc +++ b/libstdc++-v3/testsuite/20_util/declval/requirements/1_neg.cc @@ -19,7 +19,7 @@ // with this library; see the file COPYING3. If not see // . -// { dg-error "static assertion failed" "" { target *-*-* } 1603 } +// { dg-error "static assertion failed" "" { target *-*-* } 1615 } #include diff --git a/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc b/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc index 871bbe571e7..01a2068e6e7 100644 --- a/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc +++ b/libstdc++-v3/testsuite/20_util/make_signed/requirements/typedefs_neg.cc @@ -48,5 +48,5 @@ void test01() // { dg-error "instantiated from here" "" { target *-*-* } 40 } // { dg-error "instantiated from here" "" { target *-*-* } 42 } -// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1389 } -// { dg-error "declaration of" "" { target *-*-* } 1353 } +// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1401 } +// { dg-error "declaration of" "" { target *-*-* } 1365 } diff --git a/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc b/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc index edcce7cf0f5..7dd19d63127 100644 --- a/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc +++ b/libstdc++-v3/testsuite/20_util/make_unsigned/requirements/typedefs_neg.cc @@ -48,5 +48,5 @@ void test01() // { dg-error "instantiated from here" "" { target *-*-* } 40 } // { dg-error "instantiated from here" "" { target *-*-* } 42 } -// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1313 } -// { dg-error "declaration of" "" { target *-*-* } 1277 } +// { dg-error "invalid use of incomplete type" "" { target *-*-* } 1325 } +// { dg-error "declaration of" "" { target *-*-* } 1289 } -- 2.30.2