]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - libstdc++-v3/include/std/type_traits
Disable -Wctor-dtor-privacy warnings for some standard types
[thirdparty/gcc.git] / libstdc++-v3 / include / std / type_traits
index 4397c165e8dc0a3a725178138b21938352a619cc..7d4deb156a1616acfa51388d9cd62a967abe4d2f 100644 (file)
@@ -1,6 +1,6 @@
 // C++11 <type_traits> -*- C++ -*-
 
-// Copyright (C) 2007-2015 Free Software Foundation, Inc.
+// Copyright (C) 2007-2019 Free Software Foundation, Inc.
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
 // software; you can redistribute it and/or modify it under the
 
 #include <bits/c++config.h>
 
-#ifdef _GLIBCXX_USE_C99_STDINT_TR1
-# if defined (__UINT_LEAST16_TYPE__) && defined(__UINT_LEAST32_TYPE__)
-namespace std
-{
-  typedef __UINT_LEAST16_TYPE__ uint_least16_t;
-  typedef __UINT_LEAST32_TYPE__ uint_least32_t;
-}
-# else
-#  include <cstdint>
-# endif
-#endif
-
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -71,15 +59,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       static constexpr _Tp                  value = __v;
       typedef _Tp                           value_type;
       typedef integral_constant<_Tp, __v>   type;
-      constexpr operator value_type() const { return value; }
+      constexpr operator value_type() const noexcept { return value; }
 #if __cplusplus > 201103L
 
 #define __cpp_lib_integral_constant_callable 201304
 
-      constexpr value_type operator()() const { return value; }
+      constexpr value_type operator()() const noexcept { return value; }
 #endif
     };
-  
+
   template<typename _Tp, _Tp __v>
     constexpr _Tp integral_constant<_Tp, __v>::value;
 
@@ -92,11 +80,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<bool __v>
     using __bool_constant = integral_constant<bool, __v>;
 
+#if __cplusplus > 201402L
+# define __cpp_lib_bool_constant 201505
+  template<bool __v>
+    using bool_constant = integral_constant<bool, __v>;
+#endif
+
   // Meta programming helper types.
 
   template<bool, typename, typename>
     struct conditional;
 
+  template <typename _Type>
+    struct __type_identity {
+      using type = _Type;
+    };
+
   template<typename...>
     struct __or_;
 
@@ -145,9 +144,71 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template<typename _Pp>
     struct __not_
-    : public integral_constant<bool, !_Pp::value>
+    : public __bool_constant<!bool(_Pp::value)>
+    { };
+
+#if __cplusplus >= 201703L
+
+  template<typename... _Bn>
+    inline constexpr bool __or_v = __or_<_Bn...>::value;
+  template<typename... _Bn>
+    inline constexpr bool __and_v = __and_<_Bn...>::value;
+
+#define __cpp_lib_logical_traits 201510
+
+  template<typename... _Bn>
+    struct conjunction
+    : __and_<_Bn...>
+    { };
+
+  template<typename... _Bn>
+    struct disjunction
+    : __or_<_Bn...>
     { };
 
+  template<typename _Pp>
+    struct negation
+    : __not_<_Pp>
+    { };
+
+  template<typename... _Bn>
+    inline constexpr bool conjunction_v = conjunction<_Bn...>::value;
+
+  template<typename... _Bn>
+    inline constexpr bool disjunction_v = disjunction<_Bn...>::value;
+
+  template<typename _Pp>
+    inline constexpr bool negation_v = negation<_Pp>::value;
+
+#endif // C++17
+
+  // Forward declarations
+  template<typename>
+    struct is_reference;
+  template<typename>
+    struct is_function;
+  template<typename>
+    struct is_void;
+  template<typename>
+    struct __is_array_unknown_bounds;
+
+  // Helper functions that return false_type for incomplete classes,
+  // incomplete unions and arrays of known bound from those.
+
+  template <typename _T, size_t = sizeof(_T)>
+    constexpr true_type __is_complete_or_unbounded(__type_identity<_T>)
+    { return {}; }
+
+  template <typename _TypeIdentity,
+      typename _NestedType = typename _TypeIdentity::type>
+    constexpr typename __or_<
+      is_reference<_NestedType>,
+      is_function<_NestedType>,
+      is_void<_NestedType>,
+      __is_array_unknown_bounds<_NestedType>
+    >::type __is_complete_or_unbounded(_TypeIdentity)
+    { return {}; }
+
   // For several sfinae-friendly trait implementations we transport both the
   // result information (as the member type) and the failure information (no
   // member type). This is very similar to std::enable_if, but we cannot use
@@ -186,7 +247,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<>
     struct __is_integral_helper<bool>
     : public true_type { };
-  
+
   template<>
     struct __is_integral_helper<char>
     : public true_type { };
@@ -205,6 +266,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     : public true_type { };
 #endif
 
+#ifdef _GLIBCXX_USE_CHAR8_T
+  template<>
+    struct __is_integral_helper<char8_t>
+    : public true_type { };
+#endif
+
   template<>
     struct __is_integral_helper<char16_t>
     : public true_type { };
@@ -363,16 +430,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct is_rvalue_reference<_Tp&&>
     : public true_type { };
 
-  template<typename>
-    struct is_function;
-
   template<typename>
     struct __is_member_object_pointer_helper
     : public false_type { };
 
   template<typename _Tp, typename _Cp>
     struct __is_member_object_pointer_helper<_Tp _Cp::*>
-    : public integral_constant<bool, !is_function<_Tp>::value> { };
+    : public __not_<is_function<_Tp>>::type { };
 
   /// is_member_object_pointer
   template<typename _Tp>
@@ -387,7 +451,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template<typename _Tp, typename _Cp>
     struct __is_member_function_pointer_helper<_Tp _Cp::*>
-    : public integral_constant<bool, is_function<_Tp>::value> { };
+    : public is_function<_Tp>::type { };
 
   /// is_member_function_pointer
   template<typename _Tp>
@@ -419,100 +483,100 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct is_function
     : public false_type { };
 
-  template<typename _Res, typename... _ArgTypes>
-    struct is_function<_Res(_ArgTypes...)>
+  template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM>
+    struct is_function<_Res(_ArgTypes...) _GLIBCXX_NOEXCEPT_QUAL>
     : public true_type { };
 
-  template<typename _Res, typename... _ArgTypes>
-    struct is_function<_Res(_ArgTypes...) &>
+  template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM>
+    struct is_function<_Res(_ArgTypes...) & _GLIBCXX_NOEXCEPT_QUAL>
     : public true_type { };
 
-  template<typename _Res, typename... _ArgTypes>
-    struct is_function<_Res(_ArgTypes...) &&>
+  template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM>
+    struct is_function<_Res(_ArgTypes...) && _GLIBCXX_NOEXCEPT_QUAL>
     : public true_type { };
 
-  template<typename _Res, typename... _ArgTypes>
-    struct is_function<_Res(_ArgTypes......)>
+  template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM>
+    struct is_function<_Res(_ArgTypes......) _GLIBCXX_NOEXCEPT_QUAL>
     : public true_type { };
 
-  template<typename _Res, typename... _ArgTypes>
-    struct is_function<_Res(_ArgTypes......) &>
+  template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM>
+    struct is_function<_Res(_ArgTypes......) & _GLIBCXX_NOEXCEPT_QUAL>
     : public true_type { };
 
-  template<typename _Res, typename... _ArgTypes>
-    struct is_function<_Res(_ArgTypes......) &&>
+  template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM>
+    struct is_function<_Res(_ArgTypes......) && _GLIBCXX_NOEXCEPT_QUAL>
     : public true_type { };
 
-  template<typename _Res, typename... _ArgTypes>
-    struct is_function<_Res(_ArgTypes...) const>
+  template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM>
+    struct is_function<_Res(_ArgTypes...) const _GLIBCXX_NOEXCEPT_QUAL>
     : public true_type { };
 
-  template<typename _Res, typename... _ArgTypes>
-    struct is_function<_Res(_ArgTypes...) const &>
+  template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM>
+    struct is_function<_Res(_ArgTypes...) const & _GLIBCXX_NOEXCEPT_QUAL>
     : public true_type { };
 
-  template<typename _Res, typename... _ArgTypes>
-    struct is_function<_Res(_ArgTypes...) const &&>
+  template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM>
+    struct is_function<_Res(_ArgTypes...) const && _GLIBCXX_NOEXCEPT_QUAL>
     : public true_type { };
 
-  template<typename _Res, typename... _ArgTypes>
-    struct is_function<_Res(_ArgTypes......) const>
+  template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM>
+    struct is_function<_Res(_ArgTypes......) const _GLIBCXX_NOEXCEPT_QUAL>
     : public true_type { };
 
-  template<typename _Res, typename... _ArgTypes>
-    struct is_function<_Res(_ArgTypes......) const &>
+  template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM>
+    struct is_function<_Res(_ArgTypes......) const & _GLIBCXX_NOEXCEPT_QUAL>
     : public true_type { };
 
-  template<typename _Res, typename... _ArgTypes>
-    struct is_function<_Res(_ArgTypes......) const &&>
+  template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM>
+    struct is_function<_Res(_ArgTypes......) const && _GLIBCXX_NOEXCEPT_QUAL>
     : public true_type { };
 
-  template<typename _Res, typename... _ArgTypes>
-    struct is_function<_Res(_ArgTypes...) volatile>
+  template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM>
+    struct is_function<_Res(_ArgTypes...) volatile _GLIBCXX_NOEXCEPT_QUAL>
     : public true_type { };
 
-  template<typename _Res, typename... _ArgTypes>
-    struct is_function<_Res(_ArgTypes...) volatile &>
+  template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM>
+    struct is_function<_Res(_ArgTypes...) volatile & _GLIBCXX_NOEXCEPT_QUAL>
     : public true_type { };
 
-  template<typename _Res, typename... _ArgTypes>
-    struct is_function<_Res(_ArgTypes...) volatile &&>
+  template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM>
+    struct is_function<_Res(_ArgTypes...) volatile && _GLIBCXX_NOEXCEPT_QUAL>
     : public true_type { };
 
-  template<typename _Res, typename... _ArgTypes>
-    struct is_function<_Res(_ArgTypes......) volatile>
+  template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM>
+    struct is_function<_Res(_ArgTypes......) volatile _GLIBCXX_NOEXCEPT_QUAL>
     : public true_type { };
 
-  template<typename _Res, typename... _ArgTypes>
-    struct is_function<_Res(_ArgTypes......) volatile &>
+  template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM>
+    struct is_function<_Res(_ArgTypes......) volatile & _GLIBCXX_NOEXCEPT_QUAL>
     : public true_type { };
 
-  template<typename _Res, typename... _ArgTypes>
-    struct is_function<_Res(_ArgTypes......) volatile &&>
+  template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM>
+    struct is_function<_Res(_ArgTypes......) volatile && _GLIBCXX_NOEXCEPT_QUAL>
     : public true_type { };
 
-  template<typename _Res, typename... _ArgTypes>
-    struct is_function<_Res(_ArgTypes...) const volatile>
+  template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM>
+    struct is_function<_Res(_ArgTypes...) const volatile _GLIBCXX_NOEXCEPT_QUAL>
     : public true_type { };
 
-  template<typename _Res, typename... _ArgTypes>
-    struct is_function<_Res(_ArgTypes...) const volatile &>
+  template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM>
+    struct is_function<_Res(_ArgTypes...) const volatile & _GLIBCXX_NOEXCEPT_QUAL>
     : public true_type { };
 
-  template<typename _Res, typename... _ArgTypes>
-    struct is_function<_Res(_ArgTypes...) const volatile &&>
+  template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM>
+    struct is_function<_Res(_ArgTypes...) const volatile && _GLIBCXX_NOEXCEPT_QUAL>
     : public true_type { };
 
-  template<typename _Res, typename... _ArgTypes>
-    struct is_function<_Res(_ArgTypes......) const volatile>
+  template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM>
+    struct is_function<_Res(_ArgTypes......) const volatile _GLIBCXX_NOEXCEPT_QUAL>
     : public true_type { };
 
-  template<typename _Res, typename... _ArgTypes>
-    struct is_function<_Res(_ArgTypes......) const volatile &>
+  template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM>
+    struct is_function<_Res(_ArgTypes......) const volatile & _GLIBCXX_NOEXCEPT_QUAL>
     : public true_type { };
 
-  template<typename _Res, typename... _ArgTypes>
-    struct is_function<_Res(_ArgTypes......) const volatile &&>
+  template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM>
+    struct is_function<_Res(_ArgTypes......) const volatile && _GLIBCXX_NOEXCEPT_QUAL>
     : public true_type { };
 
 #define __cpp_lib_is_null_pointer 201309
@@ -579,7 +643,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   /// is_compound
   template<typename _Tp>
     struct is_compound
-    : public integral_constant<bool, !is_fundamental<_Tp>::value> { };
+    : public __not_<is_fundamental<_Tp>>::type { };
 
   template<typename _Tp>
     struct __is_member_pointer_helper
@@ -602,13 +666,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     : public __or_<is_object<_Tp>, is_reference<_Tp>>::type
     { };
 
-  template<typename _Res, typename... _Args>
-    struct __is_referenceable<_Res(_Args...)>
+  template<typename _Res, typename... _Args _GLIBCXX_NOEXCEPT_PARM>
+    struct __is_referenceable<_Res(_Args...) _GLIBCXX_NOEXCEPT_QUAL>
     : public true_type
     { };
 
-  template<typename _Res, typename... _Args>
-    struct __is_referenceable<_Res(_Args......)>
+  template<typename _Res, typename... _Args _GLIBCXX_NOEXCEPT_PARM>
+    struct __is_referenceable<_Res(_Args......) _GLIBCXX_NOEXCEPT_QUAL>
     : public true_type
     { };
 
@@ -622,7 +686,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
     struct is_const<_Tp const>
     : public true_type { };
-  
+
   /// is_volatile
   template<typename>
     struct is_volatile
@@ -636,32 +700,47 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
     struct is_trivial
     : public integral_constant<bool, __is_trivial(_Tp)>
-    { };
+    {
+      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
+       "template argument must be a complete class or an unbounded array");
+    };
 
   // is_trivially_copyable
   template<typename _Tp>
     struct is_trivially_copyable
     : public integral_constant<bool, __is_trivially_copyable(_Tp)>
-    { };
+    {
+      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
+       "template argument must be a complete class or an unbounded array");
+    };
 
   /// is_standard_layout
   template<typename _Tp>
     struct is_standard_layout
     : public integral_constant<bool, __is_standard_layout(_Tp)>
-    { };
+    {
+      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
+       "template argument must be a complete class or an unbounded array");
+    };
 
   /// is_pod
   // Could use is_standard_layout && is_trivial instead of the builtin.
   template<typename _Tp>
     struct is_pod
     : public integral_constant<bool, __is_pod(_Tp)>
-    { };
+    {
+      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
+       "template argument must be a complete class or an unbounded array");
+    };
 
   /// is_literal_type
   template<typename _Tp>
     struct is_literal_type
     : public integral_constant<bool, __is_literal_type(_Tp)>
-    { };
+    {
+      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
+       "template argument must be a complete class or an unbounded array");
+    };
 
   /// is_empty
   template<typename _Tp>
@@ -709,21 +788,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   /// is_unsigned
   template<typename _Tp>
     struct is_unsigned
-    : public __and_<is_arithmetic<_Tp>, __not_<is_signed<_Tp>>>::type
+    : public __and_<is_arithmetic<_Tp>, __not_<is_signed<_Tp>>>
     { };
 
 
   // Destructible and constructible type properties.
 
-  template<typename>
-    struct add_rvalue_reference;
-
   /**
    *  @brief  Utility to simplify expressions used in unevaluated operands
    *  @ingroup utilities
    */
+
+  template<typename _Tp, typename _Up = _Tp&&>
+    _Up
+    __declval(int);
+
+  template<typename _Tp>
+    _Tp
+    __declval(long);
+
   template<typename _Tp>
-    typename add_rvalue_reference<_Tp>::type declval() noexcept;
+    auto declval() noexcept -> decltype(__declval<_Tp>(0));
 
   template<typename, unsigned = 0>
     struct extent;
@@ -738,9 +823,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template<typename _Tp>
     struct __is_array_unknown_bounds
-    : public __and_<is_array<_Tp>, __not_<extent<_Tp>>>::type
+    : public __and_<is_array<_Tp>, __not_<extent<_Tp>>>
     { };
-    
+
   // In N3290 is_destructible does not say anything about function
   // types and abstract types, see LWG 2049. This implementation
   // describes function types as non-destructible and all complete
@@ -787,7 +872,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
     struct is_destructible
     : public __is_destructible_safe<_Tp>::type
-    { };
+    {
+      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
+       "template argument must be a complete class or an unbounded array");
+    };
 
   // is_nothrow_destructible requires that is_destructible is
   // satisfied as well.  We realize that by mimicing the
@@ -796,8 +884,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   struct __do_is_nt_destructible_impl
   {
     template<typename _Tp>
-      static integral_constant<bool, noexcept(declval<_Tp&>().~_Tp())>
-        __test(int);
+      static __bool_constant<noexcept(declval<_Tp&>().~_Tp())>
+      __test(int);
 
     template<typename>
       static false_type __test(...);
@@ -835,261 +923,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
     struct is_nothrow_destructible
     : public __is_nt_destructible_safe<_Tp>::type
-    { };
-
-  struct __do_is_default_constructible_impl
-  {
-    template<typename _Tp, typename = decltype(_Tp())>
-      static true_type __test(int);
-
-    template<typename>
-      static false_type __test(...);
-  };
-
-  template<typename _Tp>
-    struct __is_default_constructible_impl
-    : public __do_is_default_constructible_impl
-    {
-      typedef decltype(__test<_Tp>(0)) type;
-    };
-
-  template<typename _Tp>
-    struct __is_default_constructible_atom
-    : public __and_<__not_<is_void<_Tp>>,
-                    __is_default_constructible_impl<_Tp>>::type
-    { };
-
-  template<typename _Tp, bool = is_array<_Tp>::value>
-    struct __is_default_constructible_safe;
-
-  // 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<typename _Tp>
-    struct __is_default_constructible_safe<_Tp, true>
-    : public __and_<__is_array_known_bounds<_Tp>,
-                   __is_default_constructible_atom<typename
-                      remove_all_extents<_Tp>::type>>::type
-    { };
-
-  template<typename _Tp>
-    struct __is_default_constructible_safe<_Tp, false>
-    : public __is_default_constructible_atom<_Tp>::type
-    { };
-
-  /// is_default_constructible
-  template<typename _Tp>
-    struct is_default_constructible
-    : public __is_default_constructible_safe<_Tp>::type
-    { };
-
-
-  // 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<typename _From, typename _To, typename
-             = decltype(static_cast<_To>(declval<_From>()))>
-      static true_type __test(int);
-
-    template<typename, typename>
-      static false_type __test(...);
-  };
-
-  template<typename _From, typename _To>
-    struct __is_static_castable_impl
-    : public __do_is_static_castable_impl
-    {
-      typedef decltype(__test<_From, _To>(0)) type;
-    };
-
-  template<typename _From, typename _To>
-    struct __is_static_castable_safe
-    : public __is_static_castable_impl<_From, _To>::type
-    { };
-
-  // __is_static_castable
-  template<typename _From, typename _To>
-    struct __is_static_castable
-    : public integral_constant<bool, (__is_static_castable_safe<
-                                     _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.
-  // This form should be simplified by a single expression:
-  // ::delete ::new _Tp(declval<_Arg>()), see c++/51222.
-  struct __do_is_direct_constructible_impl
-  {
-    template<typename _Tp, typename _Arg, typename
-            = decltype(::new _Tp(declval<_Arg>()))>
-      static true_type __test(int);
-
-    template<typename, typename>
-      static false_type __test(...);
-  };
-
-  template<typename _Tp, typename _Arg>
-    struct __is_direct_constructible_impl
-    : public __do_is_direct_constructible_impl
-    {
-      typedef decltype(__test<_Tp, _Arg>(0)) type;
-    };
-
-  template<typename _Tp, typename _Arg>
-    struct __is_direct_constructible_new_safe
-    : public __and_<is_destructible<_Tp>,
-                    __is_direct_constructible_impl<_Tp, _Arg>>::type
-    { };
-
-  template<typename, typename>
-    struct is_same;
-
-  template<typename, typename>
-    struct is_base_of;
-
-  template<typename>
-    struct remove_reference;
-
-  template<typename _From, typename _To, bool
-           = __not_<__or_<is_void<_From>, 
-                          is_function<_From>>>::value>
-    struct __is_base_to_derived_ref;
-
-  // Detect whether we have a downcast situation during
-  // reference binding.
-  template<typename _From, typename _To>
-    struct __is_base_to_derived_ref<_From, _To, true>
-    {
-      typedef typename remove_cv<typename remove_reference<_From
-        >::type>::type __src_t;
-      typedef typename remove_cv<typename remove_reference<_To
-        >::type>::type __dst_t;
-      typedef __and_<__not_<is_same<__src_t, __dst_t>>,
-                    is_base_of<__src_t, __dst_t>> type;
-      static constexpr bool value = type::value;
-    };
-
-  template<typename _From, typename _To>
-    struct __is_base_to_derived_ref<_From, _To, false>
-    : public false_type
-    { };
-
-  template<typename _From, typename _To, bool
-           = __and_<is_lvalue_reference<_From>,
-                    is_rvalue_reference<_To>>::value>
-    struct __is_lvalue_to_rvalue_ref;
-
-  // Detect whether we have an lvalue of non-function type
-  // bound to a reference-compatible rvalue-reference.
-  template<typename _From, typename _To>
-    struct __is_lvalue_to_rvalue_ref<_From, _To, true>
     {
-      typedef typename remove_cv<typename remove_reference<
-        _From>::type>::type __src_t;
-      typedef typename remove_cv<typename remove_reference<
-        _To>::type>::type __dst_t;
-      typedef __and_<__not_<is_function<__src_t>>, 
-        __or_<is_same<__src_t, __dst_t>,
-                   is_base_of<__dst_t, __src_t>>> type;
-      static constexpr bool value = type::value;
+      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
+       "template argument must be a complete class or an unbounded array");
     };
 
-  template<typename _From, typename _To>
-    struct __is_lvalue_to_rvalue_ref<_From, _To, false>
-    : 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 conversions:
-  //    a) A base class value to a derived class reference
-  //    b) An lvalue to an rvalue-reference of reference-compatible 
-  //       types that are not functions
-  template<typename _Tp, typename _Arg>
-    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
-    { };
-
-  template<typename _Tp, typename _Arg>
-    struct __is_direct_constructible_new
-    : public conditional<is_reference<_Tp>::value,
-                        __is_direct_constructible_ref_cast<_Tp, _Arg>,
-                        __is_direct_constructible_new_safe<_Tp, _Arg>
-                        >::type
-    { };
-
-  template<typename _Tp, typename _Arg>
-    struct __is_direct_constructible
-    : public __is_direct_constructible_new<_Tp, _Arg>::type
+  template<typename _Tp, typename... _Args>
+    struct __is_constructible_impl
+    : public __bool_constant<__is_constructible(_Tp, _Args...)>
     { };
 
-  // Since default-construction and binary direct-initialization have
-  // been handled separately, the implementation of the remaining
-  // n-ary construction cases is rather straightforward. We can use
-  // here a functional cast, because array types are excluded anyway
-  // and this form is never interpreted as a C cast.
-  struct __do_is_nary_constructible_impl
-  {
-    template<typename _Tp, typename... _Args, typename
-             = decltype(_Tp(declval<_Args>()...))>
-      static true_type __test(int);
-
-    template<typename, typename...>
-      static false_type __test(...);
-  };
-
+  /// is_constructible
   template<typename _Tp, typename... _Args>
-    struct __is_nary_constructible_impl
-    : public __do_is_nary_constructible_impl
+    struct is_constructible
+      : public __is_constructible_impl<_Tp, _Args...>
     {
-      typedef decltype(__test<_Tp, _Args...>(0)) type;
+      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
+       "template argument must be a complete class or an unbounded array");
     };
 
-  template<typename _Tp, typename... _Args>
-    struct __is_nary_constructible
-    : public __is_nary_constructible_impl<_Tp, _Args...>::type
+  /// is_default_constructible
+  template<typename _Tp>
+    struct is_default_constructible
+    : public __is_constructible_impl<_Tp>::type
     {
-      static_assert(sizeof...(_Args) > 1,
-                    "Only useful for > 1 arguments");
+      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
+       "template argument must be a complete class or an unbounded array");
     };
 
-  template<typename _Tp, typename... _Args>
-    struct __is_constructible_impl
-    : public __is_nary_constructible<_Tp, _Args...>
-    { };
-
-  template<typename _Tp, typename _Arg>
-    struct __is_constructible_impl<_Tp, _Arg>
-    : public __is_direct_constructible<_Tp, _Arg>
-    { };
-
-  template<typename _Tp>
-    struct __is_constructible_impl<_Tp>
-    : public is_default_constructible<_Tp>
-    { };
-
-  /// is_constructible
-  template<typename _Tp, typename... _Args>
-    struct is_constructible
-    : public __is_constructible_impl<_Tp, _Args...>::type
-    { };
-
   template<typename _Tp, bool = __is_referenceable<_Tp>::value>
     struct __is_copy_constructible_impl;
 
@@ -1099,14 +960,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template<typename _Tp>
     struct __is_copy_constructible_impl<_Tp, true>
-    : public is_constructible<_Tp, const _Tp&>
+    : public __is_constructible_impl<_Tp, const _Tp&>
     { };
 
   /// is_copy_constructible
   template<typename _Tp>
     struct is_copy_constructible
     : public __is_copy_constructible_impl<_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_constructible_impl;
@@ -1117,14 +981,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template<typename _Tp>
     struct __is_move_constructible_impl<_Tp, true>
-    : public is_constructible<_Tp, _Tp&&>
+    : public __is_constructible_impl<_Tp, _Tp&&>
     { };
 
   /// is_move_constructible
   template<typename _Tp>
     struct is_move_constructible
     : public __is_move_constructible_impl<_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>
     struct __is_nt_default_constructible_atom
@@ -1138,7 +1005,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct __is_nt_default_constructible_impl<_Tp, true>
     : public __and_<__is_array_known_bounds<_Tp>,
                    __is_nt_default_constructible_atom<typename
-                      remove_all_extents<_Tp>::type>>::type
+                      remove_all_extents<_Tp>::type>>
     { };
 
   template<typename _Tp>
@@ -1146,12 +1013,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     : public __is_nt_default_constructible_atom<_Tp>
     { };
 
+  template<typename _Tp>
+    using __is_nothrow_default_constructible_impl
+      = __and_<__is_constructible_impl<_Tp>,
+              __is_nt_default_constructible_impl<_Tp>>;
+
   /// is_nothrow_default_constructible
   template<typename _Tp>
     struct is_nothrow_default_constructible
-    : public __and_<is_default_constructible<_Tp>,
-                    __is_nt_default_constructible_impl<_Tp>>::type
-    { };
+    : public __is_nothrow_default_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");
+    };
 
   template<typename _Tp, typename... _Args>
     struct __is_nt_constructible_impl
@@ -1166,15 +1040,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template<typename _Tp>
     struct __is_nt_constructible_impl<_Tp>
-    : public is_nothrow_default_constructible<_Tp>
+    : public __is_nothrow_default_constructible_impl<_Tp>
+    { };
+
+  template<typename _Tp, typename... _Args>
+    struct __is_nothrow_constructible_impl
+    : public __and_<__is_constructible_impl<_Tp, _Args...>,
+                   __is_nt_constructible_impl<_Tp, _Args...>>
     { };
 
   /// is_nothrow_constructible
   template<typename _Tp, typename... _Args>
     struct is_nothrow_constructible
-    : public __and_<is_constructible<_Tp, _Args...>,
-                   __is_nt_constructible_impl<_Tp, _Args...>>::type
-    { };
+    : public __is_nothrow_constructible_impl<_Tp, _Args...>::type
+    {
+      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_nothrow_copy_constructible_impl;
@@ -1185,14 +1067,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template<typename _Tp>
     struct __is_nothrow_copy_constructible_impl<_Tp, true>
-    : public is_nothrow_constructible<_Tp, const _Tp&>
+    : public __is_nothrow_constructible_impl<_Tp, const _Tp&>
     { };
 
   /// is_nothrow_copy_constructible
   template<typename _Tp>
     struct is_nothrow_copy_constructible
-    : public __is_nothrow_copy_constructible_impl<_Tp>
-    { };
+    : public __is_nothrow_copy_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");
+    };
 
   template<typename _Tp, bool = __is_referenceable<_Tp>::value>
     struct __is_nothrow_move_constructible_impl;
@@ -1203,36 +1088,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template<typename _Tp>
     struct __is_nothrow_move_constructible_impl<_Tp, true>
-    : public is_nothrow_constructible<_Tp, _Tp&&>
+    : public __is_nothrow_constructible_impl<_Tp, _Tp&&>
     { };
 
   /// is_nothrow_move_constructible
   template<typename _Tp>
     struct is_nothrow_move_constructible
-    : public __is_nothrow_move_constructible_impl<_Tp>
-    { };
-
-  template<typename _Tp, typename _Up>
-    class __is_assignable_helper
+    : public __is_nothrow_move_constructible_impl<_Tp>::type
     {
-      template<typename _Tp1, typename _Up1,
-              typename = decltype(declval<_Tp1>() = declval<_Up1>())>
-       static true_type
-       __test(int);
-
-      template<typename, typename>
-       static false_type
-       __test(...);
-
-    public:
-      typedef decltype(__test<_Tp, _Up>(0)) 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 __is_assignable_helper<_Tp, _Up>::type
-    { };
+    : public __bool_constant<__is_assignable(_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;
@@ -1243,14 +1118,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template<typename _Tp>
     struct __is_copy_assignable_impl<_Tp, true>
-    : public is_assignable<_Tp&, const _Tp&>
+    : public __bool_constant<__is_assignable(_Tp&, const _Tp&)>
     { };
 
   /// is_copy_assignable
   template<typename _Tp>
     struct is_copy_assignable
-    : public __is_copy_assignable_impl<_Tp>
-    { };
+    : public __is_copy_assignable_impl<_Tp>::type
+    {
+      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;
@@ -1261,26 +1139,37 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template<typename _Tp>
     struct __is_move_assignable_impl<_Tp, true>
-    : public is_assignable<_Tp&, _Tp&&>
+    : public __bool_constant<__is_assignable(_Tp&, _Tp&&)>
     { };
 
   /// is_move_assignable
   template<typename _Tp>
     struct is_move_assignable
-    : public __is_move_assignable_impl<_Tp>
-    { };
+    : public __is_move_assignable_impl<_Tp>::type
+    {
+      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
+       "template argument must be a complete class or an unbounded array");
+    };
 
   template<typename _Tp, typename _Up>
     struct __is_nt_assignable_impl
     : public integral_constant<bool, noexcept(declval<_Tp>() = declval<_Up>())>
     { };
 
+  template<typename _Tp, typename _Up>
+    struct __is_nothrow_assignable_impl
+    : public __and_<__bool_constant<__is_assignable(_Tp, _Up)>,
+                   __is_nt_assignable_impl<_Tp, _Up>>
+    { };
+
   /// is_nothrow_assignable
   template<typename _Tp, typename _Up>
     struct is_nothrow_assignable
-    : public __and_<is_assignable<_Tp, _Up>,
-                   __is_nt_assignable_impl<_Tp, _Up>>::type
-    { };
+    : public __is_nothrow_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_nt_copy_assignable_impl;
@@ -1291,14 +1180,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template<typename _Tp>
     struct __is_nt_copy_assignable_impl<_Tp, true>
-    : public is_nothrow_assignable<_Tp&, const _Tp&>
+    : 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>
-    { };
+    {
+      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;
@@ -1309,112 +1201,200 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template<typename _Tp>
     struct __is_nt_move_assignable_impl<_Tp, true>
-    : public is_nothrow_assignable<_Tp&, _Tp&&>
+    : 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>
-    { };
+    {
+      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
+       "template argument must be a complete class or an unbounded array");
+    };
 
   /// is_trivially_constructible
   template<typename _Tp, typename... _Args>
     struct is_trivially_constructible
-    : public __and_<is_constructible<_Tp, _Args...>, integral_constant<bool,
-                       __is_trivially_constructible(_Tp, _Args...)>>::type
-    { };
-  
+    : public __bool_constant<__is_trivially_constructible(_Tp, _Args...)>
+    {
+      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
+       "template argument must be a complete class or an unbounded array");
+    };
+
   /// is_trivially_default_constructible
   template<typename _Tp>
     struct is_trivially_default_constructible
-    : public is_trivially_constructible<_Tp>::type
-    { };
+    : public __bool_constant<__is_trivially_constructible(_Tp)>
+    {
+      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
+       "template argument must be a complete class or an unbounded array");
+    };
+
+  struct __do_is_implicitly_default_constructible_impl
+  {
+    template <typename _Tp>
+    static void __helper(const _Tp&);
+
+    template <typename _Tp>
+    static true_type __test(const _Tp&,
+                            decltype(__helper<const _Tp&>({}))* = 0);
+
+    static false_type __test(...);
+  };
 
-  /// is_trivially_copy_constructible
   template<typename _Tp>
-    struct is_trivially_copy_constructible
-    : public __and_<is_copy_constructible<_Tp>, 
+    struct __is_implicitly_default_constructible_impl
+    : public __do_is_implicitly_default_constructible_impl
+    {
+      typedef decltype(__test(declval<_Tp>())) type;
+    };
+
+  template<typename _Tp>
+    struct __is_implicitly_default_constructible_safe
+    : public __is_implicitly_default_constructible_impl<_Tp>::type
+    { };
+
+  template <typename _Tp>
+    struct __is_implicitly_default_constructible
+    : public __and_<__is_constructible_impl<_Tp>,
+                   __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&)>>::type
+                       __is_trivially_constructible(_Tp, const _Tp&)>>
     { };
-  
-  /// is_trivially_move_constructible
+
+  /// is_trivially_copy_constructible
   template<typename _Tp>
-    struct is_trivially_move_constructible
-    : public __and_<is_move_constructible<_Tp>, 
+    struct is_trivially_copy_constructible
+    : public __is_trivially_copy_constructible_impl<_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&&)>>::type
+                       __is_trivially_constructible(_Tp, _Tp&&)>>
     { };
 
+  /// is_trivially_move_constructible
+  template<typename _Tp>
+    struct is_trivially_move_constructible
+    : public __is_trivially_move_constructible_impl<_Tp>
+    {
+      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
+       "template argument must be a complete class or an unbounded array");
+    };
+
   /// is_trivially_assignable
   template<typename _Tp, typename _Up>
     struct is_trivially_assignable
-    : public __and_<is_assignable<_Tp, _Up>, 
-                   integral_constant<bool,
-                       __is_trivially_assignable(_Tp, _Up)>>::type
+    : public __bool_constant<__is_trivially_assignable(_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 __and_<is_copy_assignable<_Tp>, 
-                   integral_constant<bool,
-                       __is_trivially_assignable(_Tp&, const _Tp&)>>::type
-    { };
+    : public __is_trivially_copy_assignable_impl<_Tp>
+    {
+      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
+       "template argument must be a complete class or an unbounded array");
+    };
 
-  /// is_trivially_move_assignable
-  template<typename _Tp>
-    struct is_trivially_move_assignable
-    : public __and_<is_move_assignable<_Tp>, 
-                   integral_constant<bool,
-                       __is_trivially_assignable(_Tp&, _Tp&&)>>::type
-    { };
+  template<typename _Tp, bool = __is_referenceable<_Tp>::value>
+    struct __is_trivially_move_assignable_impl;
 
-  /// is_trivially_destructible
   template<typename _Tp>
-    struct is_trivially_destructible
-    : public __and_<is_destructible<_Tp>, integral_constant<bool,
-                             __has_trivial_destructor(_Tp)>>::type
-    { };
+    struct __is_trivially_move_assignable_impl<_Tp, false>
+    : public false_type { };
 
-  /// has_trivial_default_constructor (temporary legacy)
   template<typename _Tp>
-    struct has_trivial_default_constructor
-    : public integral_constant<bool, __has_trivial_constructor(_Tp)>
+    struct __is_trivially_move_assignable_impl<_Tp, true>
+    : public __bool_constant<__is_trivially_assignable(_Tp&, _Tp&&)>
     { };
 
-  /// has_trivial_copy_constructor (temporary legacy)
+  /// is_trivially_move_assignable
   template<typename _Tp>
-    struct has_trivial_copy_constructor
-    : public integral_constant<bool, __has_trivial_copy(_Tp)>
-    { };
+    struct is_trivially_move_assignable
+    : public __is_trivially_move_assignable_impl<_Tp>
+    {
+      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
+       "template argument must be a complete class or an unbounded array");
+    };
 
-  /// has_trivial_copy_assign (temporary legacy)
+  /// is_trivially_destructible
   template<typename _Tp>
-    struct has_trivial_copy_assign
-    : public integral_constant<bool, __has_trivial_assign(_Tp)>
-    { };
+    struct is_trivially_destructible
+    : public __and_<__is_destructible_safe<_Tp>,
+                   __bool_constant<__has_trivial_destructor(_Tp)>>
+    {
+      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
+       "template argument must be a complete class or an unbounded array");
+    };
+
 
   /// has_virtual_destructor
   template<typename _Tp>
     struct has_virtual_destructor
     : public integral_constant<bool, __has_virtual_destructor(_Tp)>
-    { };
+    {
+      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
+       "template argument must be a complete class or an unbounded array");
+    };
+
 
-  
   // type property queries.
 
   /// alignment_of
   template<typename _Tp>
     struct alignment_of
-    : public integral_constant<std::size_t, __alignof__(_Tp)> { };
-  
+    : public integral_constant<std::size_t, alignof(_Tp)>
+    {
+      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
+       "template argument must be a complete class or an unbounded array");
+    };
+
   /// rank
   template<typename>
     struct rank
     : public integral_constant<std::size_t, 0> { };
-   
+
   template<typename _Tp, std::size_t _Size>
     struct rank<_Tp[_Size]>
     : public integral_constant<std::size_t, 1 + rank<_Tp>::value> { };
@@ -1427,7 +1407,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename, unsigned _Uint>
     struct extent
     : public integral_constant<std::size_t, 0> { };
-  
+
   template<typename _Tp, unsigned _Uint, std::size_t _Size>
     struct extent<_Tp[_Size], _Uint>
     : public integral_constant<std::size_t,
@@ -1464,13 +1444,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
            bool = __or_<is_void<_From>, is_function<_To>,
                         is_array<_To>>::value>
     struct __is_convertible_helper
-    { typedef typename is_void<_To>::type type; };
+    {
+      typedef typename is_void<_To>::type type;
+    };
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
   template<typename _From, typename _To>
     class __is_convertible_helper<_From, _To, false>
     {
-       template<typename _To1>
-       static void __test_aux(_To1);
+      template<typename _To1>
+       static void __test_aux(_To1) noexcept;
 
       template<typename _From1, typename _To1,
               typename = decltype(__test_aux<_To1>(std::declval<_From1>()))>
@@ -1484,7 +1468,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     public:
       typedef decltype(__test<_From, _To>(0)) type;
     };
-
+#pragma GCC diagnostic pop
 
   /// is_convertible
   template<typename _From, typename _To>
@@ -1492,6 +1476,53 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     : public __is_convertible_helper<_From, _To>::type
     { };
 
+  template<typename _From, typename _To,
+           bool = __or_<is_void<_From>, is_function<_To>,
+                        is_array<_To>>::value>
+    struct __is_nt_convertible_helper
+    : is_void<_To>
+    { };
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
+  template<typename _From, typename _To>
+    class __is_nt_convertible_helper<_From, _To, false>
+    {
+      template<typename _To1>
+       static void __test_aux(_To1) noexcept;
+
+      template<typename _From1, typename _To1>
+       static
+       __bool_constant<noexcept(__test_aux<_To1>(std::declval<_From1>()))>
+       __test(int);
+
+      template<typename, typename>
+       static false_type
+       __test(...);
+
+    public:
+      using type = decltype(__test<_From, _To>(0));
+    };
+#pragma GCC diagnostic pop
+
+  // is_nothrow_convertible for C++11
+  template<typename _From, typename _To>
+    struct __is_nothrow_convertible
+    : public __is_nt_convertible_helper<_From, _To>::type
+    { };
+
+#if __cplusplus > 201703L
+  /// is_nothrow_convertible
+  template<typename _From, typename _To>
+    struct is_nothrow_convertible
+    : public __is_nt_convertible_helper<_From, _To>::type
+    { };
+
+  /// is_nothrow_convertible_v
+  template<typename _From, typename _To>
+    inline constexpr bool is_nothrow_convertible_v
+      = is_nothrow_convertible<_From, _To>::value;
+#endif // C++2a
 
   // Const-volatile modifications.
 
@@ -1503,7 +1534,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
     struct remove_const<_Tp const>
     { typedef _Tp     type; };
-  
+
   /// remove_volatile
   template<typename _Tp>
     struct remove_volatile
@@ -1512,7 +1543,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
     struct remove_volatile<_Tp volatile>
     { typedef _Tp     type; };
-  
+
   /// remove_cv
   template<typename _Tp>
     struct remove_cv
@@ -1520,17 +1551,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef typename
       remove_const<typename remove_volatile<_Tp>::type>::type     type;
     };
-  
+
   /// add_const
   template<typename _Tp>
     struct add_const
     { typedef _Tp const     type; };
-   
+
   /// add_volatile
   template<typename _Tp>
     struct add_volatile
     { typedef _Tp volatile     type; };
-  
+
   /// add_cv
   template<typename _Tp>
     struct add_cv
@@ -1655,7 +1686,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef __cv_selector<_Unqualified, _IsConst, _IsVol> __match;
 
     public:
-      typedef typename __match::__type __type; 
+      typedef typename __match::__type __type;
     };
 
   // Utility for finding the unsigned versions of signed integral types.
@@ -1687,12 +1718,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct __make_unsigned<long long>
     { typedef unsigned long long __type; };
 
-#if defined(_GLIBCXX_USE_WCHAR_T) && !defined(__WCHAR_UNSIGNED__)
-  template<>
-    struct __make_unsigned<wchar_t> : __make_unsigned<__WCHAR_TYPE__>
-    { };
-#endif
-
 #if defined(__GLIBCXX_TYPE_INT_N_0)
   template<>
     struct __make_unsigned<__GLIBCXX_TYPE_INT_N_0>
@@ -1715,7 +1740,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #endif
 
   // Select between integral and enum: not possible to be both.
-  template<typename _Tp, 
+  template<typename _Tp,
           bool _IsInt = is_integral<_Tp>::value,
           bool _IsEnum = is_enum<_Tp>::value>
     class __make_unsigned_selector;
@@ -1723,29 +1748,86 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
     class __make_unsigned_selector<_Tp, true, false>
     {
-      typedef __make_unsigned<typename remove_cv<_Tp>::type> __unsignedt;
-      typedef typename __unsignedt::__type __unsigned_type;
-      typedef __match_cv_qualifiers<_Tp, __unsigned_type> __cv_unsigned;
+      using __unsigned_type
+       = typename __make_unsigned<typename remove_cv<_Tp>::type>::__type;
 
     public:
-      typedef typename __cv_unsigned::__type __type;
+      using __type
+       = typename __match_cv_qualifiers<_Tp, __unsigned_type>::__type;
     };
 
+  class __make_unsigned_selector_base
+  {
+  protected:
+    template<typename...> struct _List { };
+
+    template<typename _Tp, typename... _Up>
+      struct _List<_Tp, _Up...> : _List<_Up...>
+      { static constexpr size_t __size = sizeof(_Tp); };
+
+    template<size_t _Sz, typename _Tp, bool = (_Sz <= _Tp::__size)>
+      struct __select;
+
+    template<size_t _Sz, typename _Uint, typename... _UInts>
+      struct __select<_Sz, _List<_Uint, _UInts...>, true>
+      { using __type = _Uint; };
+
+    template<size_t _Sz, typename _Uint, typename... _UInts>
+      struct __select<_Sz, _List<_Uint, _UInts...>, false>
+      : __select<_Sz, _List<_UInts...>>
+      { };
+  };
+
+  // Choose unsigned integer type with the smallest rank and same size as _Tp
   template<typename _Tp>
     class __make_unsigned_selector<_Tp, false, true>
+    : __make_unsigned_selector_base
     {
       // With -fshort-enums, an enum may be as small as a char.
-      typedef unsigned char __smallest;
-      static const bool __b0 = sizeof(_Tp) <= sizeof(__smallest);
-      static const bool __b1 = sizeof(_Tp) <= sizeof(unsigned short);
-      static const bool __b2 = sizeof(_Tp) <= sizeof(unsigned int);
-      typedef conditional<__b2, unsigned int, unsigned long> __cond2;
-      typedef typename __cond2::type __cond2_type;
-      typedef conditional<__b1, unsigned short, __cond2_type> __cond1;
-      typedef typename __cond1::type __cond1_type;
+      using _UInts = _List<unsigned char, unsigned short, unsigned int,
+                          unsigned long, unsigned long long>;
+
+      using __unsigned_type = typename __select<sizeof(_Tp), _UInts>::__type;
 
     public:
-      typedef typename conditional<__b0, __smallest, __cond1_type>::type __type;
+      using __type
+       = typename __match_cv_qualifiers<_Tp, __unsigned_type>::__type;
+    };
+
+  // wchar_t, char8_t, char16_t and char32_t are integral types but are
+  // neither signed integer types nor unsigned integer types, so must be
+  // transformed to the unsigned integer type with the smallest rank.
+  // Use the partial specialization for enumeration types to do that.
+#if defined(_GLIBCXX_USE_WCHAR_T)
+  template<>
+    struct __make_unsigned<wchar_t>
+    {
+      using __type
+       = typename __make_unsigned_selector<wchar_t, false, true>::__type;
+    };
+#endif
+
+#ifdef _GLIBCXX_USE_CHAR8_T
+  template<>
+    struct __make_unsigned<char8_t>
+    {
+      using __type
+       = typename __make_unsigned_selector<char8_t, false, true>::__type;
+    };
+#endif
+
+  template<>
+    struct __make_unsigned<char16_t>
+    {
+      using __type
+       = typename __make_unsigned_selector<char16_t, false, true>::__type;
+    };
+
+  template<>
+    struct __make_unsigned<char32_t>
+    {
+      using __type
+       = typename __make_unsigned_selector<char32_t, false, true>::__type;
     };
 
   // Given an integral/enum type, return the corresponding unsigned
@@ -1753,7 +1835,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // Primary template.
   /// make_unsigned
   template<typename _Tp>
-    struct make_unsigned 
+    struct make_unsigned
     { typedef typename __make_unsigned_selector<_Tp>::__type type; };
 
   // Integral, but don't define.
@@ -1790,21 +1872,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct __make_signed<unsigned long long>
     { typedef signed long long __type; };
 
-#if defined(_GLIBCXX_USE_WCHAR_T) && defined(__WCHAR_UNSIGNED__)
-  template<>
-    struct __make_signed<wchar_t> : __make_signed<__WCHAR_TYPE__>
-    { };
-#endif
-
-#ifdef _GLIBCXX_USE_C99_STDINT_TR1
-  template<>
-    struct __make_signed<char16_t> : __make_signed<uint_least16_t>
-    { };
-  template<>
-    struct __make_signed<char32_t> : __make_signed<uint_least32_t>
-    { };
-#endif
-
 #if defined(__GLIBCXX_TYPE_INT_N_0)
   template<>
     struct __make_signed<unsigned __GLIBCXX_TYPE_INT_N_0>
@@ -1827,7 +1894,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #endif
 
   // Select between integral and enum: not possible to be both.
-  template<typename _Tp, 
+  template<typename _Tp,
           bool _IsInt = is_integral<_Tp>::value,
           bool _IsEnum = is_enum<_Tp>::value>
     class __make_signed_selector;
@@ -1835,29 +1902,58 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
     class __make_signed_selector<_Tp, true, false>
     {
-      typedef __make_signed<typename remove_cv<_Tp>::type> __signedt;
-      typedef typename __signedt::__type __signed_type;
-      typedef __match_cv_qualifiers<_Tp, __signed_type> __cv_signed;
+      using __signed_type
+       = typename __make_signed<typename remove_cv<_Tp>::type>::__type;
 
     public:
-      typedef typename __cv_signed::__type __type;
+      using __type
+       = typename __match_cv_qualifiers<_Tp, __signed_type>::__type;
     };
 
+  // Choose signed integer type with the smallest rank and same size as _Tp
   template<typename _Tp>
     class __make_signed_selector<_Tp, false, true>
     {
-      // With -fshort-enums, an enum may be as small as a char.
-      typedef signed char __smallest;
-      static const bool __b0 = sizeof(_Tp) <= sizeof(__smallest);
-      static const bool __b1 = sizeof(_Tp) <= sizeof(signed short);
-      static const bool __b2 = sizeof(_Tp) <= sizeof(signed int);
-      typedef conditional<__b2, signed int, signed long> __cond2;
-      typedef typename __cond2::type __cond2_type;
-      typedef conditional<__b1, signed short, __cond2_type> __cond1;
-      typedef typename __cond1::type __cond1_type;
+      typedef typename __make_unsigned_selector<_Tp>::__type __unsigned_type;
 
     public:
-      typedef typename conditional<__b0, __smallest, __cond1_type>::type __type;
+      typedef typename __make_signed_selector<__unsigned_type>::__type __type;
+    };
+
+  // wchar_t, char16_t and char32_t are integral types but are neither
+  // signed integer types nor unsigned integer types, so must be
+  // transformed to the signed integer type with the smallest rank.
+  // Use the partial specialization for enumeration types to do that.
+#if defined(_GLIBCXX_USE_WCHAR_T)
+  template<>
+    struct __make_signed<wchar_t>
+    {
+      using __type
+       = typename __make_signed_selector<wchar_t, false, true>::__type;
+    };
+#endif
+
+#if defined(_GLIBCXX_USE_CHAR8_T)
+  template<>
+    struct __make_signed<char8_t>
+    {
+      using __type
+       = typename __make_signed_selector<char8_t, false, true>::__type;
+    };
+#endif
+
+  template<>
+    struct __make_signed<char16_t>
+    {
+      using __type
+       = typename __make_signed_selector<char16_t, false, true>::__type;
+    };
+
+  template<>
+    struct __make_signed<char32_t>
+    {
+      using __type
+       = typename __make_signed_selector<char32_t, false, true>::__type;
     };
 
   // Given an integral/enum type, return the corresponding signed
@@ -1865,7 +1961,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // Primary template.
   /// make_signed
   template<typename _Tp>
-    struct make_signed 
+    struct make_signed
     { typedef typename __make_signed_selector<_Tp>::__type type; };
 
   // Integral, but don't define.
@@ -1947,7 +2043,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     { typedef typename remove_reference<_Tp>::type*     type; };
 
   template<typename _Tp>
-    struct add_pointer 
+    struct add_pointer
     : public __add_pointer_helper<_Tp>
     { };
 
@@ -1963,11 +2059,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template<std::size_t _Len>
     struct __aligned_storage_msa
-    { 
+    {
       union __type
       {
        unsigned char __data[_Len];
-       struct __attribute__((__aligned__)) { } __align; 
+       struct __attribute__((__aligned__)) { } __align;
       };
     };
 
@@ -1984,11 +2080,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<std::size_t _Len, std::size_t _Align =
           __alignof__(typename __aligned_storage_msa<_Len>::__type)>
     struct aligned_storage
-    { 
+    {
       union type
       {
        unsigned char __data[_Len];
-       struct __attribute__((__aligned__((_Align)))) { } __align; 
+       struct __attribute__((__aligned__((_Align)))) { } __align;
       };
     };
 
@@ -2041,28 +2137,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   // Decay trait for arrays and functions, used for perfect forwarding
   // in make_pair, make_tuple, etc.
-  template<typename _Up, 
+  template<typename _Up,
           bool _IsArray = is_array<_Up>::value,
-          bool _IsFunction = is_function<_Up>::value> 
+          bool _IsFunction = is_function<_Up>::value>
     struct __decay_selector;
 
   // NB: DR 705.
-  template<typename _Up> 
+  template<typename _Up>
     struct __decay_selector<_Up, false, false>
     { typedef typename remove_cv<_Up>::type __type; };
 
-  template<typename _Up> 
+  template<typename _Up>
     struct __decay_selector<_Up, true, false>
     { typedef typename remove_extent<_Up>::type* __type; };
 
-  template<typename _Up> 
+  template<typename _Up>
     struct __decay_selector<_Up, false, true>
     { typedef typename add_pointer<_Up>::type __type; };
 
   /// decay
-  template<typename _Tp> 
-    class decay 
-    { 
+  template<typename _Tp>
+    class decay
+    {
       typedef typename remove_reference<_Tp>::type __remove_type;
 
     public:
@@ -2096,7 +2192,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // Primary template.
   /// Define a member typedef @c type only if a boolean constant is true.
   template<bool, typename _Tp = void>
-    struct enable_if 
+    struct enable_if
     { };
 
   // Partial specialization for true.
@@ -2118,6 +2214,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct conditional<false, _Iftrue, _Iffalse>
     { typedef _Iffalse type; };
 
+  // __void_t (std::void_t for C++11)
+  template<typename...> using __void_t = void;
+
   /// common_type
   template<typename... _Tp>
     struct common_type;
@@ -2127,85 +2226,118 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   struct __do_common_type_impl
   {
     template<typename _Tp, typename _Up>
-      static __success_type<typename decay<decltype
-                           (true ? std::declval<_Tp>()
-                            : std::declval<_Up>())>::type> _S_test(int);
+      using __cond_t
+       = decltype(true ? std::declval<_Tp>() : std::declval<_Up>());
+
+    template<typename _Tp, typename _Up>
+      static __success_type<typename decay<__cond_t<_Tp, _Up>>::type>
+      _S_test(int);
 
     template<typename, typename>
-      static __failure_type _S_test(...);
+      static __failure_type
+      _S_test(...);
   };
 
-  template<typename _Tp, typename _Up>
-    struct __common_type_impl
-    : private __do_common_type_impl
-    {
-      typedef decltype(_S_test<_Tp, _Up>(0)) type;
-    };
-
-  struct __do_member_type_wrapper
-  {
-    template<typename _Tp>
-      static __success_type<typename _Tp::type> _S_test(int);
+  // If sizeof...(T) is zero, there shall be no member type.
+  template<>
+    struct common_type<>
+    { };
 
-    template<typename>
-      static __failure_type _S_test(...);
-  };
+  // If sizeof...(T) is one, the same type, if any, as common_type_t<T0, T0>.
+  template<typename _Tp0>
+    struct common_type<_Tp0>
+    : public common_type<_Tp0, _Tp0>
+    { };
 
-  template<typename _Tp>
-    struct __member_type_wrapper
-    : private __do_member_type_wrapper
+  // If sizeof...(T) is two, ...
+  template<typename _Tp1, typename _Tp2,
+          typename _Dp1 = typename decay<_Tp1>::type,
+          typename _Dp2 = typename decay<_Tp2>::type>
+    struct __common_type_impl
     {
-      typedef decltype(_S_test<_Tp>(0)) type;
+      // If is_same_v<T1, D1> is false or is_same_v<T2, D2> is false,
+      // let C denote the same type, if any, as common_type_t<D1, D2>.
+      using type = common_type<_Dp1, _Dp2>;
     };
 
-  template<typename _CTp, typename... _Args>
-    struct __expanded_common_type_wrapper
+  template<typename _Tp1, typename _Tp2>
+    struct __common_type_impl<_Tp1, _Tp2, _Tp1, _Tp2>
+    : private __do_common_type_impl
     {
-      typedef common_type<typename _CTp::type, _Args...> type;
+      // Otherwise, if decay_t<decltype(false ? declval<D1>() : declval<D2>())>
+      // denotes a valid type, let C denote that type.
+      using type = decltype(_S_test<_Tp1, _Tp2>(0));
     };
 
-  template<typename... _Args>
-    struct __expanded_common_type_wrapper<__failure_type, _Args...>
-    { typedef __failure_type type; };
+  // If sizeof...(T) is two, ...
+  template<typename _Tp1, typename _Tp2>
+    struct common_type<_Tp1, _Tp2>
+    : public __common_type_impl<_Tp1, _Tp2>::type
+    { };
+
+  template<typename...>
+    struct __common_type_pack
+    { };
 
-  template<typename _Tp>
-    struct common_type<_Tp>
-    { typedef typename decay<_Tp>::type type; };
+  template<typename, typename, typename = void>
+    struct __common_type_fold;
 
-  template<typename _Tp, typename _Up>
-    struct common_type<_Tp, _Up>
-    : public __common_type_impl<_Tp, _Up>::type
+  // If sizeof...(T) is greater than two, ...
+  template<typename _Tp1, typename _Tp2, typename... _Rp>
+    struct common_type<_Tp1, _Tp2, _Rp...>
+    : public __common_type_fold<common_type<_Tp1, _Tp2>,
+                               __common_type_pack<_Rp...>>
+    { };
+
+  // Let C denote the same type, if any, as common_type_t<T1, T2>.
+  // If there is such a type C, type shall denote the same type, if any,
+  // as common_type_t<C, R...>.
+  template<typename _CTp, typename... _Rp>
+    struct __common_type_fold<_CTp, __common_type_pack<_Rp...>,
+                             __void_t<typename _CTp::type>>
+    : public common_type<typename _CTp::type, _Rp...>
     { };
 
-  template<typename _Tp, typename _Up, typename... _Vp>
-    struct common_type<_Tp, _Up, _Vp...>
-    : public __expanded_common_type_wrapper<typename __member_type_wrapper<
-               common_type<_Tp, _Up>>::type, _Vp...>::type
+  // Otherwise, there shall be no member type.
+  template<typename _CTp, typename _Rp>
+    struct __common_type_fold<_CTp, _Rp, void>
+    { };
+
+  template<typename _Tp, bool = is_enum<_Tp>::value>
+    struct __underlying_type_impl
+    {
+      using type = __underlying_type(_Tp);
+    };
+
+  template<typename _Tp>
+    struct __underlying_type_impl<_Tp, false>
     { };
 
   /// The underlying type of an enum.
   template<typename _Tp>
     struct underlying_type
-    {
-      typedef __underlying_type(_Tp) type;
-    };
+    : public __underlying_type_impl<_Tp>
+    { };
 
   template<typename _Tp>
     struct __declval_protector
     {
       static const bool __stop = false;
-      static typename add_rvalue_reference<_Tp>::type __delegate();
     };
 
   template<typename _Tp>
-    inline typename add_rvalue_reference<_Tp>::type
-    declval() noexcept
+    auto declval() noexcept -> decltype(__declval<_Tp>(0))
     {
       static_assert(__declval_protector<_Tp>::__stop,
                    "declval() must not be used!");
-      return __declval_protector<_Tp>::__delegate();
+      return __declval<_Tp>(0);
     }
 
+  // __remove_cvref_t (std::remove_cvref_t for C++11).
+  template<typename _Tp>
+    using __remove_cvref_t
+     = typename remove_cv<typename remove_reference<_Tp>::type>::type;
+
   /// result_of
   template<typename _Signature>
     class result_of;
@@ -2214,13 +2346,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 #define __cpp_lib_result_of_sfinae 201210
 
+  struct __invoke_memfun_ref { };
+  struct __invoke_memfun_deref { };
+  struct __invoke_memobj_ref { };
+  struct __invoke_memobj_deref { };
+  struct __invoke_other { };
+
+  // Associate a tag type with a specialization of __success_type.
+  template<typename _Tp, typename _Tag>
+    struct __result_of_success : __success_type<_Tp>
+    { using __invoke_type = _Tag; };
+
   // [func.require] paragraph 1 bullet 1:
   struct __result_of_memfun_ref_impl
   {
     template<typename _Fp, typename _Tp1, typename... _Args>
-      static __success_type<decltype(
+      static __result_of_success<decltype(
       (std::declval<_Tp1>().*std::declval<_Fp>())(std::declval<_Args>()...)
-      )> _S_test(int);
+      ), __invoke_memfun_ref> _S_test(int);
 
     template<typename...>
       static __failure_type _S_test(...);
@@ -2237,9 +2380,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   struct __result_of_memfun_deref_impl
   {
     template<typename _Fp, typename _Tp1, typename... _Args>
-      static __success_type<decltype(
+      static __result_of_success<decltype(
       ((*std::declval<_Tp1>()).*std::declval<_Fp>())(std::declval<_Args>()...)
-      )> _S_test(int);
+      ), __invoke_memfun_deref> _S_test(int);
 
     template<typename...>
       static __failure_type _S_test(...);
@@ -2256,9 +2399,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   struct __result_of_memobj_ref_impl
   {
     template<typename _Fp, typename _Tp1>
-      static __success_type<decltype(
+      static __result_of_success<decltype(
       std::declval<_Tp1>().*std::declval<_Fp>()
-      )> _S_test(int);
+      ), __invoke_memobj_ref> _S_test(int);
 
     template<typename, typename>
       static __failure_type _S_test(...);
@@ -2275,9 +2418,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   struct __result_of_memobj_deref_impl
   {
     template<typename _Fp, typename _Tp1>
-      static __success_type<decltype(
+      static __result_of_success<decltype(
       (*std::declval<_Tp1>()).*std::declval<_Fp>()
-      )> _S_test(int);
+      ), __invoke_memobj_deref> _S_test(int);
 
     template<typename, typename>
       static __failure_type _S_test(...);
@@ -2296,8 +2439,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Res, typename _Class, typename _Arg>
     struct __result_of_memobj<_Res _Class::*, _Arg>
     {
-      typedef typename remove_cv<typename remove_reference<
-        _Arg>::type>::type _Argval;
+      typedef __remove_cvref_t<_Arg> _Argval;
       typedef _Res _Class::* _MemPtr;
       typedef typename conditional<__or_<is_same<_Argval, _Class>,
         is_base_of<_Class, _Argval>>::value,
@@ -2312,16 +2454,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Res, typename _Class, typename _Arg, typename... _Args>
     struct __result_of_memfun<_Res _Class::*, _Arg, _Args...>
     {
-      typedef typename remove_cv<typename remove_reference<
-        _Arg>::type>::type _Argval;
+      typedef typename remove_reference<_Arg>::type _Argval;
       typedef _Res _Class::* _MemPtr;
-      typedef typename conditional<__or_<is_same<_Argval, _Class>,
-        is_base_of<_Class, _Argval>>::value,
+      typedef typename conditional<is_base_of<_Class, _Argval>::value,
         __result_of_memfun_ref<_MemPtr, _Arg, _Args...>,
         __result_of_memfun_deref<_MemPtr, _Arg, _Args...>
       >::type::type type;
     };
 
+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+  // 2219.  INVOKE-ing a pointer to member with a reference_wrapper
+  //        as the object expression
+
+  // Used by result_of, invoke etc. to unwrap a reference_wrapper.
+  template<typename _Tp, typename _Up = __remove_cvref_t<_Tp>>
+    struct __inv_unwrap
+    {
+      using type = _Tp;
+    };
+
+  template<typename _Tp, typename _Up>
+    struct __inv_unwrap<_Tp, reference_wrapper<_Up>>
+    {
+      using type = _Up&;
+    };
+
   template<bool, bool, typename _Functor, typename... _ArgTypes>
     struct __result_of_impl
     {
@@ -2330,21 +2487,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template<typename _MemPtr, typename _Arg>
     struct __result_of_impl<true, false, _MemPtr, _Arg>
-    : public __result_of_memobj<typename decay<_MemPtr>::type, _Arg>
+    : public __result_of_memobj<typename decay<_MemPtr>::type,
+                               typename __inv_unwrap<_Arg>::type>
     { };
 
   template<typename _MemPtr, typename _Arg, typename... _Args>
     struct __result_of_impl<false, true, _MemPtr, _Arg, _Args...>
-    : public __result_of_memfun<typename decay<_MemPtr>::type, _Arg, _Args...>
+    : public __result_of_memfun<typename decay<_MemPtr>::type,
+                               typename __inv_unwrap<_Arg>::type, _Args...>
     { };
 
   // [func.require] paragraph 1 bullet 5:
   struct __result_of_other_impl
   {
     template<typename _Fn, typename... _Args>
-      static __success_type<decltype(
+      static __result_of_success<decltype(
       std::declval<_Fn>()(std::declval<_Args>()...)
-      )> _S_test(int);
+      ), __invoke_other> _S_test(int);
 
     template<typename...>
       static __failure_type _S_test(...);
@@ -2357,8 +2516,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef decltype(_S_test<_Functor, _ArgTypes...>(0)) type;
     };
 
+  // __invoke_result (std::invoke_result for C++11)
   template<typename _Functor, typename... _ArgTypes>
-    struct result_of<_Functor(_ArgTypes...)>
+    struct __invoke_result
     : public __result_of_impl<
         is_member_object_pointer<
           typename remove_reference<_Functor>::type
@@ -2366,11 +2526,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
         is_member_function_pointer<
           typename remove_reference<_Functor>::type
         >::value,
-           _Functor, _ArgTypes...
+       _Functor, _ArgTypes...
       >::type
     { };
 
-#if __cplusplus > 201103L
+  template<typename _Functor, typename... _ArgTypes>
+    struct result_of<_Functor(_ArgTypes...)>
+    : public __invoke_result<_Functor, _ArgTypes...>
+    { };
+
+#if __cplusplus >= 201402L
   /// Alias template for aligned_storage
   template<size_t _Len, size_t _Align =
            __alignof__(typename __aligned_storage_msa<_Len>::__type)>
@@ -2402,9 +2567,46 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   /// Alias template for result_of
   template<typename _Tp>
     using result_of_t = typename result_of<_Tp>::type;
+#endif // C++14
+
+  // __enable_if_t (std::enable_if_t for C++11)
+  template<bool _Cond, typename _Tp = void>
+    using __enable_if_t = typename enable_if<_Cond, _Tp>::type;
+
+#if __cplusplus >= 201703L || !defined(__STRICT_ANSI__) // c++17 or gnu++11
+#define __cpp_lib_void_t 201411
+  /// A metafunction that always yields void, used for detecting valid types.
+  template<typename...> using void_t = void;
 #endif
 
-  template<typename...> using __void_t = void;
+  /// Implementation of the detection idiom (negative case).
+  template<typename _Default, typename _AlwaysVoid,
+          template<typename...> class _Op, typename... _Args>
+    struct __detector
+    {
+      using value_t = false_type;
+      using type = _Default;
+    };
+
+  /// Implementation of the detection idiom (positive case).
+  template<typename _Default, template<typename...> class _Op,
+           typename... _Args>
+    struct __detector<_Default, __void_t<_Op<_Args...>>, _Op, _Args...>
+    {
+      using value_t = true_type;
+      using type = _Op<_Args...>;
+    };
+
+  // Detect whether _Op<_Args...> is a valid type, use _Default if not.
+  template<typename _Default, template<typename...> class _Op,
+          typename... _Args>
+    using __detected_or = __detector<_Default, void, _Op, _Args...>;
+
+  // _Op<_Args...> if that is a valid type, otherwise _Default.
+  template<typename _Default, template<typename...> class _Op,
+          typename... _Args>
+    using __detected_or_t
+      = typename __detected_or<_Default, _Op, _Args...>::type;
 
   /// @} group metaprogramming
 
@@ -2422,6 +2624,636 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     : true_type                                                                \
     { };
 
+  template <typename _Tp>
+    struct __is_swappable;
+
+  template <typename _Tp>
+    struct __is_nothrow_swappable;
+
+  template<typename... _Elements>
+    class tuple;
+
+  template<typename>
+    struct __is_tuple_like_impl : false_type
+    { };
+
+  template<typename... _Tps>
+    struct __is_tuple_like_impl<tuple<_Tps...>> : true_type
+    { };
+
+  // Internal type trait that allows us to sfinae-protect tuple_cat.
+  template<typename _Tp>
+    struct __is_tuple_like
+    : public __is_tuple_like_impl<__remove_cvref_t<_Tp>>::type
+    { };
+
+  template<typename _Tp>
+    inline
+    typename enable_if<__and_<__not_<__is_tuple_like<_Tp>>,
+                             is_move_constructible<_Tp>,
+                             is_move_assignable<_Tp>>::value>::type
+    swap(_Tp&, _Tp&)
+    noexcept(__and_<is_nothrow_move_constructible<_Tp>,
+                   is_nothrow_move_assignable<_Tp>>::value);
+
+  template<typename _Tp, size_t _Nm>
+    inline
+    typename enable_if<__is_swappable<_Tp>::value>::type
+    swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm])
+    noexcept(__is_nothrow_swappable<_Tp>::value);
+
+  namespace __swappable_details {
+    using std::swap;
+
+    struct __do_is_swappable_impl
+    {
+      template<typename _Tp, typename
+               = decltype(swap(std::declval<_Tp&>(), std::declval<_Tp&>()))>
+        static true_type __test(int);
+
+      template<typename>
+        static false_type __test(...);
+    };
+
+    struct __do_is_nothrow_swappable_impl
+    {
+      template<typename _Tp>
+        static __bool_constant<
+          noexcept(swap(std::declval<_Tp&>(), std::declval<_Tp&>()))
+        > __test(int);
+
+      template<typename>
+        static false_type __test(...);
+    };
+
+  } // namespace __swappable_details
+
+  template<typename _Tp>
+    struct __is_swappable_impl
+    : public __swappable_details::__do_is_swappable_impl
+    {
+      typedef decltype(__test<_Tp>(0)) type;
+    };
+
+  template<typename _Tp>
+    struct __is_nothrow_swappable_impl
+    : public __swappable_details::__do_is_nothrow_swappable_impl
+    {
+      typedef decltype(__test<_Tp>(0)) type;
+    };
+
+  template<typename _Tp>
+    struct __is_swappable
+    : public __is_swappable_impl<_Tp>::type
+    { };
+
+  template<typename _Tp>
+    struct __is_nothrow_swappable
+    : public __is_nothrow_swappable_impl<_Tp>::type
+    { };
+
+#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
+#define __cpp_lib_is_swappable 201603
+  /// Metafunctions used for detecting swappable types: p0185r1
+
+  /// is_swappable
+  template<typename _Tp>
+    struct is_swappable
+    : public __is_swappable_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_nothrow_swappable
+  template<typename _Tp>
+    struct is_nothrow_swappable
+    : public __is_nothrow_swappable_impl<_Tp>::type
+    {
+      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
+       "template argument must be a complete class or an unbounded array");
+    };
+
+#if __cplusplus >= 201402L
+  /// is_swappable_v
+  template<typename _Tp>
+    _GLIBCXX17_INLINE constexpr bool is_swappable_v =
+      is_swappable<_Tp>::value;
+
+  /// is_nothrow_swappable_v
+  template<typename _Tp>
+    _GLIBCXX17_INLINE constexpr bool is_nothrow_swappable_v =
+      is_nothrow_swappable<_Tp>::value;
+#endif // __cplusplus >= 201402L
+
+  namespace __swappable_with_details {
+    using std::swap;
+
+    struct __do_is_swappable_with_impl
+    {
+      template<typename _Tp, typename _Up, typename
+               = decltype(swap(std::declval<_Tp>(), std::declval<_Up>())),
+               typename
+               = decltype(swap(std::declval<_Up>(), std::declval<_Tp>()))>
+        static true_type __test(int);
+
+      template<typename, typename>
+        static false_type __test(...);
+    };
+
+    struct __do_is_nothrow_swappable_with_impl
+    {
+      template<typename _Tp, typename _Up>
+        static __bool_constant<
+          noexcept(swap(std::declval<_Tp>(), std::declval<_Up>()))
+          &&
+          noexcept(swap(std::declval<_Up>(), std::declval<_Tp>()))
+        > __test(int);
+
+      template<typename, typename>
+        static false_type __test(...);
+    };
+
+  } // namespace __swappable_with_details
+
+  template<typename _Tp, typename _Up>
+    struct __is_swappable_with_impl
+    : public __swappable_with_details::__do_is_swappable_with_impl
+    {
+      typedef decltype(__test<_Tp, _Up>(0)) type;
+    };
+
+  // Optimization for the homogenous lvalue case, not required:
+  template<typename _Tp>
+    struct __is_swappable_with_impl<_Tp&, _Tp&>
+    : public __swappable_details::__do_is_swappable_impl
+    {
+      typedef decltype(__test<_Tp&>(0)) type;
+    };
+
+  template<typename _Tp, typename _Up>
+    struct __is_nothrow_swappable_with_impl
+    : public __swappable_with_details::__do_is_nothrow_swappable_with_impl
+    {
+      typedef decltype(__test<_Tp, _Up>(0)) type;
+    };
+
+  // Optimization for the homogenous lvalue case, not required:
+  template<typename _Tp>
+    struct __is_nothrow_swappable_with_impl<_Tp&, _Tp&>
+    : public __swappable_details::__do_is_nothrow_swappable_impl
+    {
+      typedef decltype(__test<_Tp&>(0)) type;
+    };
+
+  /// is_swappable_with
+  template<typename _Tp, typename _Up>
+    struct is_swappable_with
+    : public __is_swappable_with_impl<_Tp, _Up>::type
+    { };
+
+  /// is_nothrow_swappable_with
+  template<typename _Tp, typename _Up>
+    struct is_nothrow_swappable_with
+    : public __is_nothrow_swappable_with_impl<_Tp, _Up>::type
+    { };
+
+#if __cplusplus >= 201402L
+  /// is_swappable_with_v
+  template<typename _Tp, typename _Up>
+    _GLIBCXX17_INLINE constexpr bool is_swappable_with_v =
+      is_swappable_with<_Tp, _Up>::value;
+
+  /// is_nothrow_swappable_with_v
+  template<typename _Tp, typename _Up>
+    _GLIBCXX17_INLINE constexpr bool is_nothrow_swappable_with_v =
+      is_nothrow_swappable_with<_Tp, _Up>::value;
+#endif // __cplusplus >= 201402L
+
+#endif// c++1z or gnu++11
+
+  // __is_invocable (std::is_invocable for C++11)
+
+  template<typename _Result, typename _Ret, typename = void>
+    struct __is_invocable_impl : false_type { };
+
+  template<typename _Result, typename _Ret>
+    struct __is_invocable_impl<_Result, _Ret, __void_t<typename _Result::type>>
+    : __or_<is_void<_Ret>, is_convertible<typename _Result::type, _Ret>>::type
+    { };
+
+  template<typename _Fn, typename... _ArgTypes>
+    struct __is_invocable
+    : __is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, void>::type
+    { };
+
+  template<typename _Fn, typename _Tp, typename... _Args>
+    constexpr bool __call_is_nt(__invoke_memfun_ref)
+    {
+      using _Up = typename __inv_unwrap<_Tp>::type;
+      return noexcept((std::declval<_Up>().*std::declval<_Fn>())(
+           std::declval<_Args>()...));
+    }
+
+  template<typename _Fn, typename _Tp, typename... _Args>
+    constexpr bool __call_is_nt(__invoke_memfun_deref)
+    {
+      return noexcept(((*std::declval<_Tp>()).*std::declval<_Fn>())(
+           std::declval<_Args>()...));
+    }
+
+  template<typename _Fn, typename _Tp>
+    constexpr bool __call_is_nt(__invoke_memobj_ref)
+    {
+      using _Up = typename __inv_unwrap<_Tp>::type;
+      return noexcept(std::declval<_Up>().*std::declval<_Fn>());
+    }
+
+  template<typename _Fn, typename _Tp>
+    constexpr bool __call_is_nt(__invoke_memobj_deref)
+    {
+      return noexcept((*std::declval<_Tp>()).*std::declval<_Fn>());
+    }
+
+  template<typename _Fn, typename... _Args>
+    constexpr bool __call_is_nt(__invoke_other)
+    {
+      return noexcept(std::declval<_Fn>()(std::declval<_Args>()...));
+    }
+
+  template<typename _Result, typename _Fn, typename... _Args>
+    struct __call_is_nothrow
+    : __bool_constant<
+       std::__call_is_nt<_Fn, _Args...>(typename _Result::__invoke_type{})
+      >
+    { };
+
+  template<typename _Fn, typename... _Args>
+    using __call_is_nothrow_
+      = __call_is_nothrow<__invoke_result<_Fn, _Args...>, _Fn, _Args...>;
+
+  // __is_nothrow_invocable (std::is_nothrow_invocable for C++11)
+  template<typename _Fn, typename... _Args>
+    struct __is_nothrow_invocable
+    : __and_<__is_invocable<_Fn, _Args...>,
+             __call_is_nothrow_<_Fn, _Args...>>::type
+    { };
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
+  struct __nonesuchbase {};
+  struct __nonesuch : private __nonesuchbase {
+    ~__nonesuch() = delete;
+    __nonesuch(__nonesuch const&) = delete;
+    void operator=(__nonesuch const&) = delete;
+  };
+#pragma GCC diagnostic pop
+
+#if __cplusplus >= 201703L
+# define __cpp_lib_is_invocable 201703
+
+  /// std::invoke_result
+  template<typename _Functor, typename... _ArgTypes>
+    struct invoke_result
+    : public __invoke_result<_Functor, _ArgTypes...>
+    { };
+
+  /// std::invoke_result_t
+  template<typename _Fn, typename... _Args>
+    using invoke_result_t = typename invoke_result<_Fn, _Args...>::type;
+
+  /// std::is_invocable
+  template<typename _Fn, typename... _ArgTypes>
+    struct is_invocable
+    : __is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, void>::type
+    {
+      static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}),
+       "_Fn must be a complete class or an unbounded array");
+    };
+
+  /// std::is_invocable_r
+  template<typename _Ret, typename _Fn, typename... _ArgTypes>
+    struct is_invocable_r
+    : __is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, _Ret>::type
+    {
+      static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}),
+       "_Fn must be a complete class or an unbounded array");
+    };
+
+  /// std::is_nothrow_invocable
+  template<typename _Fn, typename... _ArgTypes>
+    struct is_nothrow_invocable
+    : __and_<__is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, void>,
+            __call_is_nothrow_<_Fn, _ArgTypes...>>::type
+    {
+      static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}),
+       "_Fn must be a complete class or an unbounded array");
+    };
+
+  template<typename _Result, typename _Ret, typename = void>
+    struct __is_nt_invocable_impl : false_type { };
+
+  template<typename _Result, typename _Ret>
+    struct __is_nt_invocable_impl<_Result, _Ret,
+                                 __void_t<typename _Result::type>>
+    : __or_<is_void<_Ret>,
+           __is_nothrow_convertible<typename _Result::type, _Ret>>
+    { };
+
+  /// std::is_nothrow_invocable_r
+  template<typename _Ret, typename _Fn, typename... _ArgTypes>
+    struct is_nothrow_invocable_r
+    : __and_<__is_nt_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, _Ret>,
+             __call_is_nothrow_<_Fn, _ArgTypes...>>::type
+    { };
+
+  /// std::is_invocable_v
+  template<typename _Fn, typename... _Args>
+    inline constexpr bool is_invocable_v = is_invocable<_Fn, _Args...>::value;
+
+  /// std::is_nothrow_invocable_v
+  template<typename _Fn, typename... _Args>
+    inline constexpr bool is_nothrow_invocable_v
+      = is_nothrow_invocable<_Fn, _Args...>::value;
+
+  /// std::is_invocable_r_v
+  template<typename _Ret, typename _Fn, typename... _Args>
+    inline constexpr bool is_invocable_r_v
+      = is_invocable_r<_Ret, _Fn, _Args...>::value;
+
+  /// std::is_nothrow_invocable_r_v
+  template<typename _Ret, typename _Fn, typename... _Args>
+    inline constexpr bool is_nothrow_invocable_r_v
+      = is_nothrow_invocable_r<_Ret, _Fn, _Args...>::value;
+#endif // C++17
+
+#if __cplusplus >= 201703L
+# define __cpp_lib_type_trait_variable_templates 201510L
+template <typename _Tp>
+  inline constexpr bool is_void_v = is_void<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_null_pointer_v = is_null_pointer<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_integral_v = is_integral<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_floating_point_v = is_floating_point<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_array_v = is_array<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_pointer_v = is_pointer<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_lvalue_reference_v =
+    is_lvalue_reference<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_rvalue_reference_v =
+    is_rvalue_reference<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_member_object_pointer_v =
+    is_member_object_pointer<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_member_function_pointer_v =
+    is_member_function_pointer<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_enum_v = is_enum<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_union_v = is_union<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_class_v = is_class<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_function_v = is_function<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_reference_v = is_reference<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_object_v = is_object<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_scalar_v = is_scalar<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_compound_v = is_compound<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_member_pointer_v = is_member_pointer<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_const_v = is_const<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_volatile_v = is_volatile<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_trivial_v = is_trivial<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_trivially_copyable_v =
+    is_trivially_copyable<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_standard_layout_v = is_standard_layout<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_pod_v = is_pod<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_literal_type_v = is_literal_type<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_empty_v = is_empty<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_polymorphic_v = is_polymorphic<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_abstract_v = is_abstract<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_final_v = is_final<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_signed_v = is_signed<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_unsigned_v = is_unsigned<_Tp>::value;
+template <typename _Tp, typename... _Args>
+  inline constexpr bool is_constructible_v =
+    is_constructible<_Tp, _Args...>::value;
+template <typename _Tp>
+  inline constexpr bool is_default_constructible_v =
+    is_default_constructible<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_copy_constructible_v =
+    is_copy_constructible<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_move_constructible_v =
+    is_move_constructible<_Tp>::value;
+template <typename _Tp, typename _Up>
+  inline constexpr bool is_assignable_v = is_assignable<_Tp, _Up>::value;
+template <typename _Tp>
+  inline constexpr bool is_copy_assignable_v = is_copy_assignable<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_move_assignable_v = is_move_assignable<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_destructible_v = is_destructible<_Tp>::value;
+template <typename _Tp, typename... _Args>
+  inline constexpr bool is_trivially_constructible_v =
+    is_trivially_constructible<_Tp, _Args...>::value;
+template <typename _Tp>
+  inline constexpr bool is_trivially_default_constructible_v =
+    is_trivially_default_constructible<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_trivially_copy_constructible_v =
+    is_trivially_copy_constructible<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_trivially_move_constructible_v =
+    is_trivially_move_constructible<_Tp>::value;
+template <typename _Tp, typename _Up>
+  inline constexpr bool is_trivially_assignable_v =
+    is_trivially_assignable<_Tp, _Up>::value;
+template <typename _Tp>
+  inline constexpr bool is_trivially_copy_assignable_v =
+    is_trivially_copy_assignable<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_trivially_move_assignable_v =
+    is_trivially_move_assignable<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_trivially_destructible_v =
+    is_trivially_destructible<_Tp>::value;
+template <typename _Tp, typename... _Args>
+  inline constexpr bool is_nothrow_constructible_v =
+    is_nothrow_constructible<_Tp, _Args...>::value;
+template <typename _Tp>
+  inline constexpr bool is_nothrow_default_constructible_v =
+    is_nothrow_default_constructible<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_nothrow_copy_constructible_v =
+    is_nothrow_copy_constructible<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_nothrow_move_constructible_v =
+    is_nothrow_move_constructible<_Tp>::value;
+template <typename _Tp, typename _Up>
+  inline constexpr bool is_nothrow_assignable_v =
+    is_nothrow_assignable<_Tp, _Up>::value;
+template <typename _Tp>
+  inline constexpr bool is_nothrow_copy_assignable_v =
+    is_nothrow_copy_assignable<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_nothrow_move_assignable_v =
+    is_nothrow_move_assignable<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool is_nothrow_destructible_v =
+    is_nothrow_destructible<_Tp>::value;
+template <typename _Tp>
+  inline constexpr bool has_virtual_destructor_v =
+    has_virtual_destructor<_Tp>::value;
+template <typename _Tp>
+  inline constexpr size_t alignment_of_v = alignment_of<_Tp>::value;
+template <typename _Tp>
+  inline constexpr size_t rank_v = rank<_Tp>::value;
+template <typename _Tp, unsigned _Idx = 0>
+  inline constexpr size_t extent_v = extent<_Tp, _Idx>::value;
+template <typename _Tp, typename _Up>
+  inline constexpr bool is_same_v = is_same<_Tp, _Up>::value;
+template <typename _Base, typename _Derived>
+  inline constexpr bool is_base_of_v = is_base_of<_Base, _Derived>::value;
+template <typename _From, typename _To>
+  inline constexpr bool is_convertible_v = is_convertible<_From, _To>::value;
+
+#ifdef _GLIBCXX_HAVE_BUILTIN_HAS_UNIQ_OBJ_REP
+# define __cpp_lib_has_unique_object_representations 201606
+  /// has_unique_object_representations
+  template<typename _Tp>
+    struct has_unique_object_representations
+    : bool_constant<__has_unique_object_representations(
+      remove_cv_t<remove_all_extents_t<_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>
+    inline constexpr bool has_unique_object_representations_v
+      = has_unique_object_representations<_Tp>::value;
+#endif
+
+#ifdef _GLIBCXX_HAVE_BUILTIN_IS_AGGREGATE
+# define __cpp_lib_is_aggregate 201703
+  /// is_aggregate
+  template<typename _Tp>
+    struct is_aggregate
+    : bool_constant<__is_aggregate(remove_cv_t<_Tp>)>
+    { };
+
+  /// is_aggregate_v
+  template<typename _Tp>
+    inline constexpr bool is_aggregate_v = is_aggregate<_Tp>::value;
+#endif
+#endif // C++17
+
+#if __cplusplus > 201703L
+  /// Byte order
+  enum class endian
+  {
+    little = __ORDER_LITTLE_ENDIAN__,
+    big    = __ORDER_BIG_ENDIAN__,
+    native = __BYTE_ORDER__
+  };
+
+  /// Remove references and cv-qualifiers.
+  template<typename _Tp>
+    struct remove_cvref
+    {
+      using type = __remove_cvref_t<_Tp>;
+    };
+
+  template<typename _Tp>
+    using remove_cvref_t = __remove_cvref_t<_Tp>;
+
+  /// Identity metafunction.
+  template<typename _Tp>
+    struct type_identity { using type = _Tp; };
+
+  template<typename _Tp>
+    using type_identity_t = typename type_identity<_Tp>::type;
+
+  /// Unwrap a reference_wrapper
+  template<typename _Tp>
+    struct unwrap_reference { using type = _Tp; };
+
+  template<typename _Tp>
+    struct unwrap_reference<reference_wrapper<_Tp>> { using type = _Tp&; };
+
+  template<typename _Tp>
+    using unwrap_reference_t = typename unwrap_reference<_Tp>::type;
+
+  /// Decay type and if it's a reference_wrapper, unwrap it
+  template<typename _Tp>
+    struct unwrap_ref_decay { using type = unwrap_reference_t<decay_t<_Tp>>; };
+
+  template<typename _Tp>
+    using unwrap_ref_decay_t = typename unwrap_ref_decay<_Tp>::type;
+
+#define __cpp_lib_bounded_array_traits 201902L
+
+  /// True for a type that is an array of known bound.
+  template<typename _Tp>
+    struct is_bounded_array
+    : public __is_array_known_bounds<_Tp>
+    { };
+
+  /// True for a type that is an array of unknown bound.
+  template<typename _Tp>
+    struct is_unbounded_array
+    : public __is_array_unknown_bounds<_Tp>
+    { };
+
+  template<typename _Tp>
+    inline constexpr bool is_bounded_array_v
+      = is_bounded_array<_Tp>::value;
+
+  template<typename _Tp>
+    inline constexpr bool is_unbounded_array_v
+      = is_unbounded_array<_Tp>::value;
+
+#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED
+
+#define __cpp_lib_is_constant_evaluated 201811L
+
+  constexpr inline bool
+  is_constant_evaluated() noexcept
+  { return __builtin_is_constant_evaluated(); }
+#endif
+
+#endif // C++2a
+
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std