Tested powerpc64le-linux, pushed to trunk.
-- >8 --
We can replace some class template helpers with alias templates, which
are cheaper to instantiate.
For example, replace the __is_copy_constructible_impl class template
with an alias template that uses just evaluates the __is_constructible
built-in, using add_lvalue_reference<const T> to get the argument type
in a way that works for non-referenceable types. For a given
specialization of is_copy_constructible this results in the same number
of class templates being instantiated (for the common case of non-void,
non-function types), but the add_lvalue_reference instantiations are not
specific to the is_copy_constructible specialization and so can be
reused by other traits. Previously __is_copy_constructible_impl was a
distinct class template and its specializations were never used for
anything except is_copy_constructible.
With the new definitions of these traits that don't depend on helper
classes, it becomes more practical to optimize the
is_xxx_constructible_v variable templates to avoid instantiations.
Previously doing so would have meant two entirely separate
implementation strategies for these traits.
libstdc++-v3/ChangeLog:
* include/std/type_traits (__is_constructible_impl): Replace
class template with alias template.
(is_default_constructible, is_nothrow_constructible)
(is_nothrow_constructible): Simplify base-specifier.
(__is_copy_constructible_impl, __is_move_constructible_impl)
(__is_nothrow_copy_constructible_impl)
(__is_nothrow_move_constructible_impl): Remove class templates.
(is_copy_constructible, is_move_constructible)
(is_nothrow_constructible, is_nothrow_default_constructible)
(is_nothrow_copy_constructible, is_nothrow_move_constructible):
Adjust base-specifiers to use __is_constructible_impl.
(__is_copy_assignable_impl, __is_move_assignable_impl)
(__is_nt_copy_assignable_impl, __is_nt_move_assignable_impl):
Remove class templates.
(__is_assignable_impl): New alias template.
(is_assignable, is_copy_assignable, is_move_assignable):
Adjust base-specifiers to use new alias template.
(is_nothrow_copy_assignable, is_nothrow_move_assignable):
Adjust base-specifiers to use existing alias template.
(__is_trivially_constructible_impl): New alias template.
(is_trivially_constructible, is_trivially_default_constructible)
(is_trivially_copy_constructible)
(is_trivially_move_constructible): Adjust base-specifiers to use
new alias template.
(__is_trivially_assignable_impl): New alias template.
(is_trivially_assignable, is_trivially_copy_assignable)
(is_trivially_move_assignable): Adjust base-specifier to use
new alias template.
(__add_lval_ref_t, __add_rval_ref_t): New alias templates.
(add_lvalue_reference, add_rvalue_reference): Use new alias
templates.
---
libstdc++-v3/include/std/type_traits | 249 +++++++--------------------
1 file changed, 62 insertions(+), 187 deletions(-)
@@ -1001,9 +1001,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// @cond undocumented
template<typename _Tp, typename... _Args>
- struct __is_constructible_impl
- : public __bool_constant<__is_constructible(_Tp, _Args...)>
- { };
+ using __is_constructible_impl
+ = __bool_constant<__is_constructible(_Tp, _Args...)>;
/// @endcond
/// is_constructible
@@ -1018,7 +1017,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// is_default_constructible
template<typename _Tp>
struct is_default_constructible
- : public __is_constructible_impl<_Tp>::type
+ : public __is_constructible_impl<_Tp>
{
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
"template argument must be a complete class or an unbounded array");
@@ -1026,22 +1025,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// @cond undocumented
template<typename _Tp, bool = __is_referenceable<_Tp>::value>
- struct __is_copy_constructible_impl;
+ struct __add_lvalue_reference_helper
+ { using type = _Tp; };
template<typename _Tp>
- struct __is_copy_constructible_impl<_Tp, false>
- : public false_type { };
+ struct __add_lvalue_reference_helper<_Tp, true>
+ { using type = _Tp&; };
template<typename _Tp>
- struct __is_copy_constructible_impl<_Tp, true>
- : public __is_constructible_impl<_Tp, const _Tp&>
- { };
+ using __add_lval_ref_t = typename __add_lvalue_reference_helper<_Tp>::type;
/// @endcond
/// is_copy_constructible
template<typename _Tp>
struct is_copy_constructible
- : public __is_copy_constructible_impl<_Tp>
+ : public __is_constructible_impl<_Tp, __add_lval_ref_t<const _Tp>>
{
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
"template argument must be a complete class or an unbounded array");
@@ -1049,22 +1047,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// @cond undocumented
template<typename _Tp, bool = __is_referenceable<_Tp>::value>
- struct __is_move_constructible_impl;
+ struct __add_rvalue_reference_helper
+ { using type = _Tp; };
template<typename _Tp>
- struct __is_move_constructible_impl<_Tp, false>
- : public false_type { };
+ struct __add_rvalue_reference_helper<_Tp, true>
+ { using type = _Tp&&; };
template<typename _Tp>
- struct __is_move_constructible_impl<_Tp, true>
- : public __is_constructible_impl<_Tp, _Tp&&>
- { };
+ using __add_rval_ref_t = typename __add_rvalue_reference_helper<_Tp>::type;
/// @endcond
/// is_move_constructible
template<typename _Tp>
struct is_move_constructible
- : public __is_move_constructible_impl<_Tp>
+ : public __is_constructible_impl<_Tp, __add_rval_ref_t<_Tp>>
{
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
"template argument must be a complete class or an unbounded array");
@@ -1079,7 +1076,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// is_nothrow_constructible
template<typename _Tp, typename... _Args>
struct is_nothrow_constructible
- : public __is_nothrow_constructible_impl<_Tp, _Args...>::type
+ : public __is_nothrow_constructible_impl<_Tp, _Args...>
{
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
"template argument must be a complete class or an unbounded array");
@@ -1088,112 +1085,68 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// is_nothrow_default_constructible
template<typename _Tp>
struct is_nothrow_default_constructible
- : public __bool_constant<__is_nothrow_constructible(_Tp)>
+ : public __is_nothrow_constructible_impl<_Tp>
{
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
"template argument must be a complete class or an unbounded array");
};
- /// @cond undocumented
- template<typename _Tp, bool = __is_referenceable<_Tp>::value>
- struct __is_nothrow_copy_constructible_impl;
-
- template<typename _Tp>
- struct __is_nothrow_copy_constructible_impl<_Tp, false>
- : public false_type { };
-
- template<typename _Tp>
- struct __is_nothrow_copy_constructible_impl<_Tp, true>
- : public __is_nothrow_constructible_impl<_Tp, const _Tp&>
- { };
- /// @endcond
-
/// is_nothrow_copy_constructible
template<typename _Tp>
struct is_nothrow_copy_constructible
- : public __is_nothrow_copy_constructible_impl<_Tp>::type
+ : public __is_nothrow_constructible_impl<_Tp, __add_lval_ref_t<const _Tp>>
+ {
+ static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
+ "template argument must be a complete class or an unbounded array");
+ };
+
+ /// is_nothrow_move_constructible
+ template<typename _Tp>
+ struct is_nothrow_move_constructible
+ : public __is_nothrow_constructible_impl<_Tp, __add_rval_ref_t<_Tp>>
{
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
"template argument must be a complete class or an unbounded array");
};
/// @cond undocumented
- template<typename _Tp, bool = __is_referenceable<_Tp>::value>
- struct __is_nothrow_move_constructible_impl;
-
- template<typename _Tp>
- struct __is_nothrow_move_constructible_impl<_Tp, false>
- : public false_type { };
-
- template<typename _Tp>
- struct __is_nothrow_move_constructible_impl<_Tp, true>
- : public __is_nothrow_constructible_impl<_Tp, _Tp&&>
- { };
+ template<typename _Tp, typename _Up>
+ using __is_assignable_impl = __bool_constant<__is_assignable(_Tp, _Up)>;
/// @endcond
- /// is_nothrow_move_constructible
- template<typename _Tp>
- struct is_nothrow_move_constructible
- : public __is_nothrow_move_constructible_impl<_Tp>::type
- {
- static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
- "template argument must be a complete class or an unbounded array");
- };
-
/// is_assignable
template<typename _Tp, typename _Up>
struct is_assignable
- : public __bool_constant<__is_assignable(_Tp, _Up)>
+ : public __is_assignable_impl<_Tp, _Up>
{
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
"template argument must be a complete class or an unbounded array");
};
- template<typename _Tp, bool = __is_referenceable<_Tp>::value>
- struct __is_copy_assignable_impl;
-
- template<typename _Tp>
- struct __is_copy_assignable_impl<_Tp, false>
- : public false_type { };
-
- template<typename _Tp>
- struct __is_copy_assignable_impl<_Tp, true>
- : public __bool_constant<__is_assignable(_Tp&, const _Tp&)>
- { };
-
/// is_copy_assignable
template<typename _Tp>
struct is_copy_assignable
- : public __is_copy_assignable_impl<_Tp>::type
+ : public __is_assignable_impl<__add_lval_ref_t<_Tp>,
+ __add_lval_ref_t<const _Tp>>
{
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
"template argument must be a complete class or an unbounded array");
};
- template<typename _Tp, bool = __is_referenceable<_Tp>::value>
- struct __is_move_assignable_impl;
-
- template<typename _Tp>
- struct __is_move_assignable_impl<_Tp, false>
- : public false_type { };
-
- template<typename _Tp>
- struct __is_move_assignable_impl<_Tp, true>
- : public __bool_constant<__is_assignable(_Tp&, _Tp&&)>
- { };
-
/// is_move_assignable
template<typename _Tp>
struct is_move_assignable
- : public __is_move_assignable_impl<_Tp>::type
+ : public __is_assignable_impl<__add_lval_ref_t<_Tp>, __add_rval_ref_t<_Tp>>
{
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
"template argument must be a complete class or an unbounded array");
};
+ /// @cond undocumented
template<typename _Tp, typename _Up>
using __is_nothrow_assignable_impl
= __bool_constant<__is_nothrow_assignable(_Tp, _Up)>;
+ /// @endcond
/// is_nothrow_assignable
template<typename _Tp, typename _Up>
@@ -1204,52 +1157,36 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
"template argument must be a complete class or an unbounded array");
};
- template<typename _Tp, bool = __is_referenceable<_Tp>::value>
- struct __is_nt_copy_assignable_impl;
-
- template<typename _Tp>
- struct __is_nt_copy_assignable_impl<_Tp, false>
- : public false_type { };
-
- template<typename _Tp>
- struct __is_nt_copy_assignable_impl<_Tp, true>
- : public __is_nothrow_assignable_impl<_Tp&, const _Tp&>
- { };
-
/// is_nothrow_copy_assignable
template<typename _Tp>
struct is_nothrow_copy_assignable
- : public __is_nt_copy_assignable_impl<_Tp>
+ : public __is_nothrow_assignable_impl<__add_lval_ref_t<_Tp>,
+ __add_lval_ref_t<const _Tp>>
{
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
"template argument must be a complete class or an unbounded array");
};
- template<typename _Tp, bool = __is_referenceable<_Tp>::value>
- struct __is_nt_move_assignable_impl;
-
- template<typename _Tp>
- struct __is_nt_move_assignable_impl<_Tp, false>
- : public false_type { };
-
- template<typename _Tp>
- struct __is_nt_move_assignable_impl<_Tp, true>
- : public __is_nothrow_assignable_impl<_Tp&, _Tp&&>
- { };
-
/// is_nothrow_move_assignable
template<typename _Tp>
struct is_nothrow_move_assignable
- : public __is_nt_move_assignable_impl<_Tp>
+ : public __is_nothrow_assignable_impl<__add_lval_ref_t<_Tp>,
+ __add_rval_ref_t<_Tp>>
{
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
"template argument must be a complete class or an unbounded array");
};
+ /// @cond undocumented
+ template<typename _Tp, typename... _Args>
+ using __is_trivially_constructible_impl
+ = __bool_constant<__is_trivially_constructible(_Tp, _Args...)>;
+ /// @endcond
+
/// is_trivially_constructible
template<typename _Tp, typename... _Args>
struct is_trivially_constructible
- : public __bool_constant<__is_trivially_constructible(_Tp, _Args...)>
+ : public __is_trivially_constructible_impl<_Tp, _Args...>
{
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
"template argument must be a complete class or an unbounded array");
@@ -1258,7 +1195,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// is_trivially_default_constructible
template<typename _Tp>
struct is_trivially_default_constructible
- : public __bool_constant<__is_trivially_constructible(_Tp)>
+ : public __is_trivially_constructible_impl<_Tp>
{
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
"template argument must be a complete class or an unbounded array");
@@ -1294,98 +1231,54 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__is_implicitly_default_constructible_safe<_Tp>>
{ };
- template<typename _Tp, bool = __is_referenceable<_Tp>::value>
- struct __is_trivially_copy_constructible_impl;
-
- template<typename _Tp>
- struct __is_trivially_copy_constructible_impl<_Tp, false>
- : public false_type { };
-
- template<typename _Tp>
- struct __is_trivially_copy_constructible_impl<_Tp, true>
- : public __and_<__is_copy_constructible_impl<_Tp>,
- integral_constant<bool,
- __is_trivially_constructible(_Tp, const _Tp&)>>
- { };
-
/// is_trivially_copy_constructible
template<typename _Tp>
struct is_trivially_copy_constructible
- : public __is_trivially_copy_constructible_impl<_Tp>
+ : public __is_trivially_constructible_impl<_Tp, __add_lval_ref_t<const _Tp>>
{
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
"template argument must be a complete class or an unbounded array");
};
- template<typename _Tp, bool = __is_referenceable<_Tp>::value>
- struct __is_trivially_move_constructible_impl;
-
- template<typename _Tp>
- struct __is_trivially_move_constructible_impl<_Tp, false>
- : public false_type { };
-
- template<typename _Tp>
- struct __is_trivially_move_constructible_impl<_Tp, true>
- : public __and_<__is_move_constructible_impl<_Tp>,
- integral_constant<bool,
- __is_trivially_constructible(_Tp, _Tp&&)>>
- { };
-
/// is_trivially_move_constructible
template<typename _Tp>
struct is_trivially_move_constructible
- : public __is_trivially_move_constructible_impl<_Tp>
+ : public __is_trivially_constructible_impl<_Tp, __add_rval_ref_t<_Tp>>
{
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
"template argument must be a complete class or an unbounded array");
};
+ /// @cond undocumented
+ template<typename _Tp, typename _Up>
+ using __is_trivially_assignable_impl
+ = __bool_constant<__is_trivially_assignable(_Tp, _Up)>;
+ /// @endcond
+
/// is_trivially_assignable
template<typename _Tp, typename _Up>
struct is_trivially_assignable
- : public __bool_constant<__is_trivially_assignable(_Tp, _Up)>
+ : public __is_trivially_assignable_impl<_Tp, _Up>
{
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
"template argument must be a complete class or an unbounded array");
};
- template<typename _Tp, bool = __is_referenceable<_Tp>::value>
- struct __is_trivially_copy_assignable_impl;
-
- template<typename _Tp>
- struct __is_trivially_copy_assignable_impl<_Tp, false>
- : public false_type { };
-
- template<typename _Tp>
- struct __is_trivially_copy_assignable_impl<_Tp, true>
- : public __bool_constant<__is_trivially_assignable(_Tp&, const _Tp&)>
- { };
-
/// is_trivially_copy_assignable
template<typename _Tp>
struct is_trivially_copy_assignable
- : public __is_trivially_copy_assignable_impl<_Tp>
+ : public __is_trivially_assignable_impl<__add_lval_ref_t<_Tp>,
+ __add_lval_ref_t<const _Tp>>
{
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
"template argument must be a complete class or an unbounded array");
};
- template<typename _Tp, bool = __is_referenceable<_Tp>::value>
- struct __is_trivially_move_assignable_impl;
-
- template<typename _Tp>
- struct __is_trivially_move_assignable_impl<_Tp, false>
- : public false_type { };
-
- template<typename _Tp>
- struct __is_trivially_move_assignable_impl<_Tp, true>
- : public __bool_constant<__is_trivially_assignable(_Tp&, _Tp&&)>
- { };
-
/// is_trivially_move_assignable
template<typename _Tp>
struct is_trivially_move_assignable
- : public __is_trivially_move_assignable_impl<_Tp>
+ : public __is_trivially_assignable_impl<__add_lval_ref_t<_Tp>,
+ __add_rval_ref_t<_Tp>>
{
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
"template argument must be a complete class or an unbounded array");
@@ -1669,33 +1562,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct remove_reference<_Tp&&>
{ typedef _Tp type; };
- template<typename _Tp, bool = __is_referenceable<_Tp>::value>
- struct __add_lvalue_reference_helper
- { typedef _Tp type; };
-
- template<typename _Tp>
- struct __add_lvalue_reference_helper<_Tp, true>
- { typedef _Tp& type; };
-
/// add_lvalue_reference
template<typename _Tp>
struct add_lvalue_reference
- : public __add_lvalue_reference_helper<_Tp>
- { };
-
- template<typename _Tp, bool = __is_referenceable<_Tp>::value>
- struct __add_rvalue_reference_helper
- { typedef _Tp type; };
-
- template<typename _Tp>
- struct __add_rvalue_reference_helper<_Tp, true>
- { typedef _Tp&& type; };
+ { using type = __add_lval_ref_t<_Tp>; };
/// add_rvalue_reference
template<typename _Tp>
struct add_rvalue_reference
- : public __add_rvalue_reference_helper<_Tp>
- { };
+ { using type = __add_rval_ref_t<_Tp>; };
#if __cplusplus > 201103L
/// Alias template for remove_reference