// C++11 <type_traits> -*- C++ -*-

// Copyright (C) 2007-2024 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
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.

// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://www.gnu.org/licenses/>.

/** @file include/type_traits
 *  This is a Standard C++ Library header.
 */

#ifndef _GLIBCXX_TYPE_TRAITS
#define _GLIBCXX_TYPE_TRAITS 1

#pragma GCC system_header

#if __cplusplus < 201103L
# include <bits/c++0x_warning.h>
#else

#include <bits/c++config.h>

#define __glibcxx_want_bool_constant
#define __glibcxx_want_bounded_array_traits
#define __glibcxx_want_has_unique_object_representations
#define __glibcxx_want_integral_constant_callable
#define __glibcxx_want_is_aggregate
#define __glibcxx_want_is_constant_evaluated
#define __glibcxx_want_is_final
#define __glibcxx_want_is_invocable
#define __glibcxx_want_is_layout_compatible
#define __glibcxx_want_is_nothrow_convertible
#define __glibcxx_want_is_null_pointer
#define __glibcxx_want_is_pointer_interconvertible
#define __glibcxx_want_is_scoped_enum
#define __glibcxx_want_is_swappable
#define __glibcxx_want_logical_traits
#define __glibcxx_want_reference_from_temporary
#define __glibcxx_want_remove_cvref
#define __glibcxx_want_result_of_sfinae
#define __glibcxx_want_transformation_trait_aliases
#define __glibcxx_want_type_identity
#define __glibcxx_want_type_trait_variable_templates
#define __glibcxx_want_unwrap_ref
#define __glibcxx_want_void_t
#include <bits/version.h>

namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION

  template<typename _Tp>
    class reference_wrapper;

  /**
   * @defgroup metaprogramming Metaprogramming
   * @ingroup utilities
   *
   * Template utilities for compile-time introspection and modification,
   * including type classification traits, type property inspection traits
   * and type transformation traits.
   *
   * @since C++11
   *
   * @{
   */

  /// integral_constant
  template<typename _Tp, _Tp __v>
    struct integral_constant
    {
      static constexpr _Tp value = __v;
      using value_type = _Tp;
      using type = integral_constant<_Tp, __v>;
      constexpr operator value_type() const noexcept { return value; }

#ifdef __cpp_lib_integral_constant_callable // C++ >= 14
      constexpr value_type operator()() const noexcept { return value; }
#endif
    };

#if ! __cpp_inline_variables
  template<typename _Tp, _Tp __v>
    constexpr _Tp integral_constant<_Tp, __v>::value;
#endif

  /// @cond undocumented
  /// bool_constant for C++11
  template<bool __v>
    using __bool_constant = integral_constant<bool, __v>;
  /// @endcond

  /// The type used as a compile-time boolean with true value.
  using true_type =  __bool_constant<true>;

  /// The type used as a compile-time boolean with false value.
  using false_type = __bool_constant<false>;

#ifdef __cpp_lib_bool_constant // C++ >= 17
  /// Alias template for compile-time boolean constant types.
  /// @since C++17
  template<bool __v>
    using bool_constant = __bool_constant<__v>;
#endif

  // Metaprogramming helper types.

  // Primary template.
  /// Define a member typedef `type` only if a boolean constant is true.
  template<bool, typename _Tp = void>
    struct enable_if
    { };

  // Partial specialization for true.
  template<typename _Tp>
    struct enable_if<true, _Tp>
    { using type = _Tp; };

  // __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;

  template<bool>
    struct __conditional
    {
      template<typename _Tp, typename>
	using type = _Tp;
    };

  template<>
    struct __conditional<false>
    {
      template<typename, typename _Up>
	using type = _Up;
    };

  // More efficient version of std::conditional_t for internal use (and C++11)
  template<bool _Cond, typename _If, typename _Else>
    using __conditional_t
      = typename __conditional<_Cond>::template type<_If, _Else>;

  /// @cond undocumented
  template <typename _Type>
    struct __type_identity
    { using type = _Type; };

  template<typename _Tp>
    using __type_identity_t = typename __type_identity<_Tp>::type;

  namespace __detail
  {
    // A variadic alias template that resolves to its first argument.
    template<typename _Tp, typename...>
      using __first_t = _Tp;

    // These are deliberately not defined.
    template<typename... _Bn>
      auto __or_fn(int) -> __first_t<false_type,
				     __enable_if_t<!bool(_Bn::value)>...>;

    template<typename... _Bn>
      auto __or_fn(...) -> true_type;

    template<typename... _Bn>
      auto __and_fn(int) -> __first_t<true_type,
				      __enable_if_t<bool(_Bn::value)>...>;

    template<typename... _Bn>
      auto __and_fn(...) -> false_type;
  } // namespace detail

  // Like C++17 std::dis/conjunction, but usable in C++11 and resolves
  // to either true_type or false_type which allows for a more efficient
  // implementation that avoids recursive class template instantiation.
  template<typename... _Bn>
    struct __or_
    : decltype(__detail::__or_fn<_Bn...>(0))
    { };

  template<typename... _Bn>
    struct __and_
    : decltype(__detail::__and_fn<_Bn...>(0))
    { };

  template<typename _Pp>
    struct __not_
    : __bool_constant<!bool(_Pp::value)>
    { };
  /// @endcond

#ifdef __cpp_lib_logical_traits // C++ >= 17

  /// @cond undocumented
  template<typename... _Bn>
    inline constexpr bool __or_v = __or_<_Bn...>::value;
  template<typename... _Bn>
    inline constexpr bool __and_v = __and_<_Bn...>::value;

  namespace __detail
  {
    template<typename /* = void */, typename _B1, typename... _Bn>
      struct __disjunction_impl
      { using type = _B1; };

    template<typename _B1, typename _B2, typename... _Bn>
      struct __disjunction_impl<__enable_if_t<!bool(_B1::value)>, _B1, _B2, _Bn...>
      { using type = typename __disjunction_impl<void, _B2, _Bn...>::type; };

    template<typename /* = void */, typename _B1, typename... _Bn>
      struct __conjunction_impl
      { using type = _B1; };

    template<typename _B1, typename _B2, typename... _Bn>
      struct __conjunction_impl<__enable_if_t<bool(_B1::value)>, _B1, _B2, _Bn...>
      { using type = typename __conjunction_impl<void, _B2, _Bn...>::type; };
  } // namespace __detail
  /// @endcond

  template<typename... _Bn>
    struct conjunction
    : __detail::__conjunction_impl<void, _Bn...>::type
    { };

  template<>
    struct conjunction<>
    : true_type
    { };

  template<typename... _Bn>
    struct disjunction
    : __detail::__disjunction_impl<void, _Bn...>::type
    { };

  template<>
    struct disjunction<>
    : false_type
    { };

  template<typename _Pp>
    struct negation
    : __not_<_Pp>::type
    { };

  /** @ingroup variable_templates
   * @{
   */
  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 // __cpp_lib_logical_traits

  // Forward declarations
  template<typename>
    struct is_reference;
  template<typename>
    struct is_function;
  template<typename>
    struct is_void;
  template<typename>
    struct remove_cv;
  template<typename>
    struct is_const;

  /// @cond undocumented
  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 _Tp, size_t = sizeof(_Tp)>
    constexpr true_type __is_complete_or_unbounded(__type_identity<_Tp>)
    { 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 {}; }

  // __remove_cv_t (std::remove_cv_t for C++11).
  template<typename _Tp>
    using __remove_cv_t = typename remove_cv<_Tp>::type;
  /// @endcond

  // Primary type categories.

  /// is_void
  template<typename _Tp>
    struct is_void
    : public false_type { };

  template<>
    struct is_void<void>
    : public true_type { };

  template<>
    struct is_void<const void>
    : public true_type { };

  template<>
    struct is_void<volatile void>
    : public true_type { };

  template<>
    struct is_void<const volatile void>
    : public true_type { };

  /// @cond undocumented
  template<typename>
    struct __is_integral_helper
    : public false_type { };

  template<>
    struct __is_integral_helper<bool>
    : public true_type { };

  template<>
    struct __is_integral_helper<char>
    : public true_type { };

  template<>
    struct __is_integral_helper<signed char>
    : public true_type { };

  template<>
    struct __is_integral_helper<unsigned char>
    : public true_type { };

  // We want is_integral<wchar_t> to be true (and make_signed/unsigned to work)
  // even when libc doesn't provide working <wchar.h> and related functions,
  // so don't check _GLIBCXX_USE_WCHAR_T here.
  template<>
    struct __is_integral_helper<wchar_t>
    : public true_type { };

#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 { };

  template<>
    struct __is_integral_helper<char32_t>
    : public true_type { };

  template<>
    struct __is_integral_helper<short>
    : public true_type { };

  template<>
    struct __is_integral_helper<unsigned short>
    : public true_type { };

  template<>
    struct __is_integral_helper<int>
    : public true_type { };

  template<>
    struct __is_integral_helper<unsigned int>
    : public true_type { };

  template<>
    struct __is_integral_helper<long>
    : public true_type { };

  template<>
    struct __is_integral_helper<unsigned long>
    : public true_type { };

  template<>
    struct __is_integral_helper<long long>
    : public true_type { };

  template<>
    struct __is_integral_helper<unsigned long long>
    : public true_type { };

  // Conditionalizing on __STRICT_ANSI__ here will break any port that
  // uses one of these types for size_t.
#if defined(__GLIBCXX_TYPE_INT_N_0)
  __extension__
  template<>
    struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_0>
    : public true_type { };

  __extension__
  template<>
    struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_0>
    : public true_type { };
#endif
#if defined(__GLIBCXX_TYPE_INT_N_1)
  __extension__
  template<>
    struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_1>
    : public true_type { };

  __extension__
  template<>
    struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_1>
    : public true_type { };
#endif
#if defined(__GLIBCXX_TYPE_INT_N_2)
  __extension__
  template<>
    struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_2>
    : public true_type { };

  __extension__
  template<>
    struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_2>
    : public true_type { };
#endif
#if defined(__GLIBCXX_TYPE_INT_N_3)
  __extension__
  template<>
    struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_3>
    : public true_type { };

  __extension__
  template<>
    struct __is_integral_helper<unsigned __GLIBCXX_TYPE_INT_N_3>
    : public true_type { };
#endif
  /// @endcond

  /// is_integral
  template<typename _Tp>
    struct is_integral
    : public __is_integral_helper<__remove_cv_t<_Tp>>::type
    { };

  /// @cond undocumented
  template<typename>
    struct __is_floating_point_helper
    : public false_type { };

  template<>
    struct __is_floating_point_helper<float>
    : public true_type { };

  template<>
    struct __is_floating_point_helper<double>
    : public true_type { };

  template<>
    struct __is_floating_point_helper<long double>
    : public true_type { };

#ifdef __STDCPP_FLOAT16_T__
  template<>
    struct __is_floating_point_helper<_Float16>
    : public true_type { };
#endif

#ifdef __STDCPP_FLOAT32_T__
  template<>
    struct __is_floating_point_helper<_Float32>
    : public true_type { };
#endif

#ifdef __STDCPP_FLOAT64_T__
  template<>
    struct __is_floating_point_helper<_Float64>
    : public true_type { };
#endif

#ifdef __STDCPP_FLOAT128_T__
  template<>
    struct __is_floating_point_helper<_Float128>
    : public true_type { };
#endif

#ifdef __STDCPP_BFLOAT16_T__
  template<>
    struct __is_floating_point_helper<__gnu_cxx::__bfloat16_t>
    : public true_type { };
#endif

#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128)
  template<>
    struct __is_floating_point_helper<__float128>
    : public true_type { };
#endif
  /// @endcond

  /// is_floating_point
  template<typename _Tp>
    struct is_floating_point
    : public __is_floating_point_helper<__remove_cv_t<_Tp>>::type
    { };

  /// is_array
#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_array)
  template<typename _Tp>
    struct is_array
    : public __bool_constant<__is_array(_Tp)>
    { };
#else
  template<typename>
    struct is_array
    : public false_type { };

  template<typename _Tp, std::size_t _Size>
    struct is_array<_Tp[_Size]>
    : public true_type { };

  template<typename _Tp>
    struct is_array<_Tp[]>
    : public true_type { };
#endif

  template<typename>
    struct __is_pointer_helper
    : public false_type { };

  template<typename _Tp>
    struct __is_pointer_helper<_Tp*>
    : public true_type { };

  /// is_pointer
  template<typename _Tp>
    struct is_pointer
    : public __is_pointer_helper<__remove_cv_t<_Tp>>::type
    { };

  /// is_lvalue_reference
  template<typename>
    struct is_lvalue_reference
    : public false_type { };

  template<typename _Tp>
    struct is_lvalue_reference<_Tp&>
    : public true_type { };

  /// is_rvalue_reference
  template<typename>
    struct is_rvalue_reference
    : public false_type { };

  template<typename _Tp>
    struct is_rvalue_reference<_Tp&&>
    : public true_type { };

  /// is_member_object_pointer
#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_member_object_pointer)
  template<typename _Tp>
    struct is_member_object_pointer
    : public __bool_constant<__is_member_object_pointer(_Tp)>
    { };
#else
  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 __not_<is_function<_Tp>>::type { };


  template<typename _Tp>
    struct is_member_object_pointer
    : public __is_member_object_pointer_helper<__remove_cv_t<_Tp>>::type
    { };
#endif

#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_member_function_pointer)
  /// is_member_function_pointer
  template<typename _Tp>
    struct is_member_function_pointer
    : public __bool_constant<__is_member_function_pointer(_Tp)>
    { };
#else
  template<typename>
    struct __is_member_function_pointer_helper
    : public false_type { };

  template<typename _Tp, typename _Cp>
    struct __is_member_function_pointer_helper<_Tp _Cp::*>
    : public is_function<_Tp>::type { };

  /// is_member_function_pointer
  template<typename _Tp>
    struct is_member_function_pointer
    : public __is_member_function_pointer_helper<__remove_cv_t<_Tp>>::type
    { };
#endif

  /// is_enum
  template<typename _Tp>
    struct is_enum
    : public __bool_constant<__is_enum(_Tp)>
    { };

  /// is_union
  template<typename _Tp>
    struct is_union
    : public __bool_constant<__is_union(_Tp)>
    { };

  /// is_class
  template<typename _Tp>
    struct is_class
    : public __bool_constant<__is_class(_Tp)>
    { };

  /// is_function
#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_function)
  template<typename _Tp>
    struct is_function
    : public __bool_constant<__is_function(_Tp)>
    { };
#else
  template<typename _Tp>
    struct is_function
    : public __bool_constant<!is_const<const _Tp>::value> { };

  template<typename _Tp>
    struct is_function<_Tp&>
    : public false_type { };

  template<typename _Tp>
    struct is_function<_Tp&&>
    : public false_type { };
#endif

#ifdef __cpp_lib_is_null_pointer // C++ >= 11
  /// is_null_pointer (LWG 2247).
  template<typename _Tp>
    struct is_null_pointer
    : public false_type { };

  template<>
    struct is_null_pointer<std::nullptr_t>
    : public true_type { };

  template<>
    struct is_null_pointer<const std::nullptr_t>
    : public true_type { };

  template<>
    struct is_null_pointer<volatile std::nullptr_t>
    : public true_type { };

  template<>
    struct is_null_pointer<const volatile std::nullptr_t>
    : public true_type { };

  /// __is_nullptr_t (deprecated extension).
  /// @deprecated Non-standard. Use `is_null_pointer` instead.
  template<typename _Tp>
    struct __is_nullptr_t
    : public is_null_pointer<_Tp>
    { } _GLIBCXX_DEPRECATED_SUGGEST("std::is_null_pointer");
#endif // __cpp_lib_is_null_pointer

  // Composite type categories.

  /// is_reference
#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_reference)
  template<typename _Tp>
    struct is_reference
    : public __bool_constant<__is_reference(_Tp)>
    { };
#else
  template<typename _Tp>
    struct is_reference
    : public false_type
    { };

  template<typename _Tp>
    struct is_reference<_Tp&>
    : public true_type
    { };

  template<typename _Tp>
    struct is_reference<_Tp&&>
    : public true_type
    { };
#endif

  /// is_arithmetic
  template<typename _Tp>
    struct is_arithmetic
    : public __or_<is_integral<_Tp>, is_floating_point<_Tp>>::type
    { };

  /// is_fundamental
  template<typename _Tp>
    struct is_fundamental
    : public __or_<is_arithmetic<_Tp>, is_void<_Tp>,
		   is_null_pointer<_Tp>>::type
    { };

  /// is_object
#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_object)
  template<typename _Tp>
    struct is_object
    : public __bool_constant<__is_object(_Tp)>
    { };
#else
  template<typename _Tp>
    struct is_object
    : public __not_<__or_<is_function<_Tp>, is_reference<_Tp>,
                          is_void<_Tp>>>::type
    { };
#endif

  template<typename>
    struct is_member_pointer;

  /// is_scalar
  template<typename _Tp>
    struct is_scalar
    : public __or_<is_arithmetic<_Tp>, is_enum<_Tp>, is_pointer<_Tp>,
                   is_member_pointer<_Tp>, is_null_pointer<_Tp>>::type
    { };

  /// is_compound
  template<typename _Tp>
    struct is_compound
    : public __bool_constant<!is_fundamental<_Tp>::value> { };

  /// is_member_pointer
#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_member_pointer)
  template<typename _Tp>
    struct is_member_pointer
    : public __bool_constant<__is_member_pointer(_Tp)>
    { };
#else
  /// @cond undocumented
  template<typename _Tp>
    struct __is_member_pointer_helper
    : public false_type { };

  template<typename _Tp, typename _Cp>
    struct __is_member_pointer_helper<_Tp _Cp::*>
    : public true_type { };
  /// @endcond

  template<typename _Tp>
    struct is_member_pointer
    : public __is_member_pointer_helper<__remove_cv_t<_Tp>>::type
    { };
#endif

  template<typename, typename>
    struct is_same;

  /// @cond undocumented
  template<typename _Tp, typename... _Types>
    using __is_one_of = __or_<is_same<_Tp, _Types>...>;

  // Check if a type is one of the signed integer types.
  __extension__
  template<typename _Tp>
    using __is_signed_integer = __is_one_of<__remove_cv_t<_Tp>,
	  signed char, signed short, signed int, signed long,
	  signed long long
#if defined(__GLIBCXX_TYPE_INT_N_0)
	  , signed __GLIBCXX_TYPE_INT_N_0
#endif
#if defined(__GLIBCXX_TYPE_INT_N_1)
	  , signed __GLIBCXX_TYPE_INT_N_1
#endif
#if defined(__GLIBCXX_TYPE_INT_N_2)
	  , signed __GLIBCXX_TYPE_INT_N_2
#endif
#if defined(__GLIBCXX_TYPE_INT_N_3)
	  , signed __GLIBCXX_TYPE_INT_N_3
#endif
	  >;

  // Check if a type is one of the unsigned integer types.
  __extension__
  template<typename _Tp>
    using __is_unsigned_integer = __is_one_of<__remove_cv_t<_Tp>,
	  unsigned char, unsigned short, unsigned int, unsigned long,
	  unsigned long long
#if defined(__GLIBCXX_TYPE_INT_N_0)
	  , unsigned __GLIBCXX_TYPE_INT_N_0
#endif
#if defined(__GLIBCXX_TYPE_INT_N_1)
	  , unsigned __GLIBCXX_TYPE_INT_N_1
#endif
#if defined(__GLIBCXX_TYPE_INT_N_2)
	  , unsigned __GLIBCXX_TYPE_INT_N_2
#endif
#if defined(__GLIBCXX_TYPE_INT_N_3)
	  , unsigned __GLIBCXX_TYPE_INT_N_3
#endif
	  >;

  // Check if a type is one of the signed or unsigned integer types.
  template<typename _Tp>
    using __is_standard_integer
      = __or_<__is_signed_integer<_Tp>, __is_unsigned_integer<_Tp>>;

  // __void_t (std::void_t for C++11)
  template<typename...> using __void_t = void;
  /// @endcond

  // Type properties.

  /// is_const
  template<typename>
    struct is_const
    : public false_type { };

  template<typename _Tp>
    struct is_const<_Tp const>
    : public true_type { };

  /// is_volatile
  template<typename>
    struct is_volatile
    : public false_type { };

  template<typename _Tp>
    struct is_volatile<_Tp volatile>
    : public true_type { };

  /// is_trivial
  template<typename _Tp>
    struct is_trivial
    : public __bool_constant<__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 __bool_constant<__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 __bool_constant<__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
   * @deprecated Deprecated in C++20.
   * Use `is_standard_layout && is_trivial` instead.
   */
  // Could use is_standard_layout && is_trivial instead of the builtin.
  template<typename _Tp>
    struct
    _GLIBCXX20_DEPRECATED_SUGGEST("is_standard_layout && is_trivial")
    is_pod
    : public __bool_constant<__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
   * @deprecated Deprecated in C++17, removed in C++20.
   * The idea of a literal type isn't useful.
   */
  template<typename _Tp>
    struct
    _GLIBCXX17_DEPRECATED
    is_literal_type
    : public __bool_constant<__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>
    struct is_empty
    : public __bool_constant<__is_empty(_Tp)>
    { };

  /// is_polymorphic
  template<typename _Tp>
    struct is_polymorphic
    : public __bool_constant<__is_polymorphic(_Tp)>
    { };

#ifdef __cpp_lib_is_final // C++ >= 14
  /// is_final
  /// @since C++14
  template<typename _Tp>
    struct is_final
    : public __bool_constant<__is_final(_Tp)>
    { };
#endif

  /// is_abstract
  template<typename _Tp>
    struct is_abstract
    : public __bool_constant<__is_abstract(_Tp)>
    { };

  /// @cond undocumented
  template<typename _Tp,
	   bool = is_arithmetic<_Tp>::value>
    struct __is_signed_helper
    : public false_type { };

  template<typename _Tp>
    struct __is_signed_helper<_Tp, true>
    : public __bool_constant<_Tp(-1) < _Tp(0)>
    { };
  /// @endcond

  /// is_signed
  template<typename _Tp>
    struct is_signed
    : public __is_signed_helper<_Tp>::type
    { };

  /// is_unsigned
  template<typename _Tp>
    struct is_unsigned
    : public __and_<is_arithmetic<_Tp>, __not_<is_signed<_Tp>>>::type
    { };

  /// @cond undocumented
  template<typename _Tp, typename _Up = _Tp&&>
    _Up
    __declval(int);

  template<typename _Tp>
    _Tp
    __declval(long);
  /// @endcond

  template<typename _Tp>
    auto declval() noexcept -> decltype(__declval<_Tp>(0));

  template<typename>
    struct remove_all_extents;

  /// @cond undocumented
  template<typename _Tp>
    struct __is_array_known_bounds
    : public false_type
    { };

  template<typename _Tp, size_t _Size>
    struct __is_array_known_bounds<_Tp[_Size]>
    : public true_type
    { };

  template<typename _Tp>
    struct __is_array_unknown_bounds
    : public false_type
    { };

  template<typename _Tp>
    struct __is_array_unknown_bounds<_Tp[]>
    : public true_type
    { };

  // Destructible and constructible type properties.

  // 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
  // object types as destructible, iff the explicit destructor
  // call expression is wellformed.
  struct __do_is_destructible_impl
  {
    template<typename _Tp, typename = decltype(declval<_Tp&>().~_Tp())>
      static true_type __test(int);

    template<typename>
      static false_type __test(...);
  };

  template<typename _Tp>
    struct __is_destructible_impl
    : public __do_is_destructible_impl
    {
      using type = decltype(__test<_Tp>(0));
    };

  template<typename _Tp,
           bool = __or_<is_void<_Tp>,
                        __is_array_unknown_bounds<_Tp>,
                        is_function<_Tp>>::value,
           bool = __or_<is_reference<_Tp>, is_scalar<_Tp>>::value>
    struct __is_destructible_safe;

  template<typename _Tp>
    struct __is_destructible_safe<_Tp, false, false>
    : public __is_destructible_impl<typename
               remove_all_extents<_Tp>::type>::type
    { };

  template<typename _Tp>
    struct __is_destructible_safe<_Tp, true, false>
    : public false_type { };

  template<typename _Tp>
    struct __is_destructible_safe<_Tp, false, true>
    : public true_type { };
  /// @endcond

  /// is_destructible
  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");
    };

  /// @cond undocumented

  // is_nothrow_destructible requires that is_destructible is
  // satisfied as well.  We realize that by mimicing the
  // implementation of is_destructible but refer to noexcept(expr)
  // instead of decltype(expr).
  struct __do_is_nt_destructible_impl
  {
    template<typename _Tp>
      static __bool_constant<noexcept(declval<_Tp&>().~_Tp())>
      __test(int);

    template<typename>
      static false_type __test(...);
  };

  template<typename _Tp>
    struct __is_nt_destructible_impl
    : public __do_is_nt_destructible_impl
    {
      using type = decltype(__test<_Tp>(0));
    };

  template<typename _Tp,
           bool = __or_<is_void<_Tp>,
                        __is_array_unknown_bounds<_Tp>,
                        is_function<_Tp>>::value,
           bool = __or_<is_reference<_Tp>, is_scalar<_Tp>>::value>
    struct __is_nt_destructible_safe;

  template<typename _Tp>
    struct __is_nt_destructible_safe<_Tp, false, false>
    : public __is_nt_destructible_impl<typename
               remove_all_extents<_Tp>::type>::type
    { };

  template<typename _Tp>
    struct __is_nt_destructible_safe<_Tp, true, false>
    : public false_type { };

  template<typename _Tp>
    struct __is_nt_destructible_safe<_Tp, false, true>
    : public true_type { };
  /// @endcond

  /// is_nothrow_destructible
  template<typename _Tp>
    struct is_nothrow_destructible
    : public __is_nt_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");
    };

  /// @cond undocumented
  template<typename _Tp, typename... _Args>
    using __is_constructible_impl
      = __bool_constant<__is_constructible(_Tp, _Args...)>;
  /// @endcond

  /// is_constructible
  template<typename _Tp, typename... _Args>
    struct is_constructible
      : public __is_constructible_impl<_Tp, _Args...>
    {
      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
	"template argument must be a complete class or an unbounded array");
    };

  /// is_default_constructible
  template<typename _Tp>
    struct is_default_constructible
    : public __is_constructible_impl<_Tp>
    {
      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
	"template argument must be a complete class or an unbounded array");
    };

  /// @cond undocumented
  template<typename _Tp, typename = void>
    struct __add_lvalue_reference_helper
    { using type = _Tp; };

  template<typename _Tp>
    struct __add_lvalue_reference_helper<_Tp, __void_t<_Tp&>>
    { using type = _Tp&; };

  template<typename _Tp>
    using __add_lval_ref_t = typename __add_lvalue_reference_helper<_Tp>::type;
  /// @endcond

  /// is_copy_constructible
  template<typename _Tp>
    struct is_copy_constructible
    : public __is_constructible_impl<_Tp, __add_lval_ref_t<const _Tp>>
    {
      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
	"template argument must be a complete class or an unbounded array");
    };

  /// @cond undocumented
  template<typename _Tp, typename = void>
    struct __add_rvalue_reference_helper
    { using type = _Tp; };

  template<typename _Tp>
    struct __add_rvalue_reference_helper<_Tp, __void_t<_Tp&&>>
    { using type = _Tp&&; };

  template<typename _Tp>
    using __add_rval_ref_t = typename __add_rvalue_reference_helper<_Tp>::type;
  /// @endcond

  /// is_move_constructible
  template<typename _Tp>
    struct is_move_constructible
    : public __is_constructible_impl<_Tp, __add_rval_ref_t<_Tp>>
    {
      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
	"template argument must be a complete class or an unbounded array");
    };

  /// @cond undocumented
  template<typename _Tp, typename... _Args>
    using __is_nothrow_constructible_impl
      = __bool_constant<__is_nothrow_constructible(_Tp, _Args...)>;
  /// @endcond

  /// is_nothrow_constructible
  template<typename _Tp, typename... _Args>
    struct is_nothrow_constructible
    : public __is_nothrow_constructible_impl<_Tp, _Args...>
    {
      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
	"template argument must be a complete class or an unbounded array");
    };

  /// is_nothrow_default_constructible
  template<typename _Tp>
    struct is_nothrow_default_constructible
    : public __is_nothrow_constructible_impl<_Tp>
    {
      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
	"template argument must be a complete class or an unbounded array");
    };

  /// is_nothrow_copy_constructible
  template<typename _Tp>
    struct is_nothrow_copy_constructible
    : public __is_nothrow_constructible_impl<_Tp, __add_lval_ref_t<const _Tp>>
    {
      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
	"template argument must be a complete class or an unbounded array");
    };

  /// is_nothrow_move_constructible
  template<typename _Tp>
    struct is_nothrow_move_constructible
    : public __is_nothrow_constructible_impl<_Tp, __add_rval_ref_t<_Tp>>
    {
      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
	"template argument must be a complete class or an unbounded array");
    };

  /// @cond undocumented
  template<typename _Tp, typename _Up>
    using __is_assignable_impl = __bool_constant<__is_assignable(_Tp, _Up)>;
  /// @endcond

  /// is_assignable
  template<typename _Tp, typename _Up>
    struct is_assignable
    : public __is_assignable_impl<_Tp, _Up>
    {
      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
	"template argument must be a complete class or an unbounded array");
    };

  /// is_copy_assignable
  template<typename _Tp>
    struct is_copy_assignable
    : public __is_assignable_impl<__add_lval_ref_t<_Tp>,
				  __add_lval_ref_t<const _Tp>>
    {
      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
	"template argument must be a complete class or an unbounded array");
    };

  /// is_move_assignable
  template<typename _Tp>
    struct is_move_assignable
    : public __is_assignable_impl<__add_lval_ref_t<_Tp>, __add_rval_ref_t<_Tp>>
    {
      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
	"template argument must be a complete class or an unbounded array");
    };

  /// @cond undocumented
  template<typename _Tp, typename _Up>
    using __is_nothrow_assignable_impl
      = __bool_constant<__is_nothrow_assignable(_Tp, _Up)>;
  /// @endcond

  /// is_nothrow_assignable
  template<typename _Tp, typename _Up>
    struct is_nothrow_assignable
    : 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");
    };

  /// is_nothrow_copy_assignable
  template<typename _Tp>
    struct is_nothrow_copy_assignable
    : public __is_nothrow_assignable_impl<__add_lval_ref_t<_Tp>,
					  __add_lval_ref_t<const _Tp>>
    {
      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
	"template argument must be a complete class or an unbounded array");
    };

  /// is_nothrow_move_assignable
  template<typename _Tp>
    struct is_nothrow_move_assignable
    : public __is_nothrow_assignable_impl<__add_lval_ref_t<_Tp>,
					  __add_rval_ref_t<_Tp>>
    {
      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
	"template argument must be a complete class or an unbounded array");
    };

  /// @cond undocumented
  template<typename _Tp, typename... _Args>
    using __is_trivially_constructible_impl
      = __bool_constant<__is_trivially_constructible(_Tp, _Args...)>;
  /// @endcond

  /// is_trivially_constructible
  template<typename _Tp, typename... _Args>
    struct is_trivially_constructible
    : public __is_trivially_constructible_impl<_Tp, _Args...>
    {
      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
	"template argument must be a complete class or an unbounded array");
    };

  /// is_trivially_default_constructible
  template<typename _Tp>
    struct is_trivially_default_constructible
    : public __is_trivially_constructible_impl<_Tp>
    {
      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
	"template argument must be a complete class or an unbounded array");
    };

#if __cpp_variable_templates && __cpp_concepts
  template<typename _Tp>
    constexpr bool __is_implicitly_default_constructible_v
      = requires (void(&__f)(_Tp)) { __f({}); };

  template<typename _Tp>
    struct __is_implicitly_default_constructible
    : __bool_constant<__is_implicitly_default_constructible_v<_Tp>>
    { };
#else
  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(...);
  };

  template<typename _Tp>
    struct __is_implicitly_default_constructible_impl
    : public __do_is_implicitly_default_constructible_impl
    {
      using type = decltype(__test(declval<_Tp>()));
    };

  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>>::type
    { };
#endif

  /// is_trivially_copy_constructible
  template<typename _Tp>
    struct is_trivially_copy_constructible
    : public __is_trivially_constructible_impl<_Tp, __add_lval_ref_t<const _Tp>>
    {
      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
	"template argument must be a complete class or an unbounded array");
    };

  /// is_trivially_move_constructible
  template<typename _Tp>
    struct is_trivially_move_constructible
    : public __is_trivially_constructible_impl<_Tp, __add_rval_ref_t<_Tp>>
    {
      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
	"template argument must be a complete class or an unbounded array");
    };

  /// @cond undocumented
  template<typename _Tp, typename _Up>
    using __is_trivially_assignable_impl
      = __bool_constant<__is_trivially_assignable(_Tp, _Up)>;
  /// @endcond

  /// is_trivially_assignable
  template<typename _Tp, typename _Up>
    struct is_trivially_assignable
    : public __is_trivially_assignable_impl<_Tp, _Up>
    {
      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
	"template argument must be a complete class or an unbounded array");
    };

  /// is_trivially_copy_assignable
  template<typename _Tp>
    struct is_trivially_copy_assignable
    : public __is_trivially_assignable_impl<__add_lval_ref_t<_Tp>,
					    __add_lval_ref_t<const _Tp>>
    {
      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
	"template argument must be a complete class or an unbounded array");
    };

  /// is_trivially_move_assignable
  template<typename _Tp>
    struct is_trivially_move_assignable
    : public __is_trivially_assignable_impl<__add_lval_ref_t<_Tp>,
					    __add_rval_ref_t<_Tp>>
    {
      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
	"template argument must be a complete class or an unbounded array");
    };

  /// is_trivially_destructible
  template<typename _Tp>
    struct is_trivially_destructible
    : public __and_<__is_destructible_safe<_Tp>,
		    __bool_constant<__has_trivial_destructor(_Tp)>>::type
    {
      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 __bool_constant<__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)>
    {
      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> { };

  template<typename _Tp>
    struct rank<_Tp[]>
    : public integral_constant<std::size_t, 1 + rank<_Tp>::value> { };

  /// extent
  template<typename, unsigned _Uint = 0>
    struct extent
    : public integral_constant<size_t, 0> { };

  template<typename _Tp, size_t _Size>
    struct extent<_Tp[_Size], 0>
    : public integral_constant<size_t, _Size> { };

  template<typename _Tp, unsigned _Uint, size_t _Size>
    struct extent<_Tp[_Size], _Uint>
    : public extent<_Tp, _Uint - 1>::type { };

  template<typename _Tp>
    struct extent<_Tp[], 0>
    : public integral_constant<size_t, 0> { };

  template<typename _Tp, unsigned _Uint>
    struct extent<_Tp[], _Uint>
    : public extent<_Tp, _Uint - 1>::type { };


  // Type relations.

  /// is_same
#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_same)
  template<typename _Tp, typename _Up>
    struct is_same
    : public __bool_constant<__is_same(_Tp, _Up)>
    { };
#else
  template<typename _Tp, typename _Up>
    struct is_same
    : public false_type
    { };

  template<typename _Tp>
    struct is_same<_Tp, _Tp>
    : public true_type
    { };
#endif

  /// is_base_of
  template<typename _Base, typename _Derived>
    struct is_base_of
    : public __bool_constant<__is_base_of(_Base, _Derived)>
    { };

#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_convertible)
  template<typename _From, typename _To>
    struct is_convertible
    : public __bool_constant<__is_convertible(_From, _To)>
    { };
#else
  template<typename _From, typename _To,
           bool = __or_<is_void<_From>, is_function<_To>,
                        is_array<_To>>::value>
    struct __is_convertible_helper
    {
      using type = typename is_void<_To>::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) noexcept;

      template<typename _From1, typename _To1,
	       typename = decltype(__test_aux<_To1>(std::declval<_From1>()))>
	static true_type
	__test(int);

      template<typename, typename>
	static false_type
	__test(...);

    public:
      using type = decltype(__test<_From, _To>(0));
    };
#pragma GCC diagnostic pop

  /// is_convertible
  template<typename _From, typename _To>
    struct is_convertible
    : public __is_convertible_helper<_From, _To>::type
    { };
#endif

  // helper trait for unique_ptr<T[]>, shared_ptr<T[]>, and span<T, N>
  template<typename _ToElementType, typename _FromElementType>
    using __is_array_convertible
      = is_convertible<_FromElementType(*)[], _ToElementType(*)[]>;

#ifdef __cpp_lib_is_nothrow_convertible // C++ >= 20

#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_nothrow_convertible)
  /// is_nothrow_convertible_v
  template<typename _From, typename _To>
    inline constexpr bool is_nothrow_convertible_v
      = __is_nothrow_convertible(_From, _To);

  /// is_nothrow_convertible
  template<typename _From, typename _To>
    struct is_nothrow_convertible
    : public bool_constant<is_nothrow_convertible_v<_From, _To>>
    { };
#else
  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
  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
#endif // __cpp_lib_is_nothrow_convertible

  // Const-volatile modifications.

  /// remove_const
  template<typename _Tp>
    struct remove_const
    { using type = _Tp; };

  template<typename _Tp>
    struct remove_const<_Tp const>
    { using type = _Tp; };

  /// remove_volatile
  template<typename _Tp>
    struct remove_volatile
    { using type = _Tp; };

  template<typename _Tp>
    struct remove_volatile<_Tp volatile>
    { using type = _Tp; };

  /// remove_cv
#if _GLIBCXX_USE_BUILTIN_TRAIT(__remove_cv)
  template<typename _Tp>
    struct remove_cv
    { using type = __remove_cv(_Tp); };
#else
  template<typename _Tp>
    struct remove_cv
    { using type = _Tp; };

  template<typename _Tp>
    struct remove_cv<const _Tp>
    { using type = _Tp; };

  template<typename _Tp>
    struct remove_cv<volatile _Tp>
    { using type = _Tp; };

  template<typename _Tp>
    struct remove_cv<const volatile _Tp>
    { using type = _Tp; };
#endif

  /// add_const
  template<typename _Tp>
    struct add_const
    { using type = _Tp const; };

  /// add_volatile
  template<typename _Tp>
    struct add_volatile
    { using type = _Tp volatile; };

  /// add_cv
  template<typename _Tp>
    struct add_cv
    { using type = _Tp const volatile; };

#ifdef __cpp_lib_transformation_trait_aliases // C++ >= 14
  /// Alias template for remove_const
  template<typename _Tp>
    using remove_const_t = typename remove_const<_Tp>::type;

  /// Alias template for remove_volatile
  template<typename _Tp>
    using remove_volatile_t = typename remove_volatile<_Tp>::type;

  /// Alias template for remove_cv
  template<typename _Tp>
    using remove_cv_t = typename remove_cv<_Tp>::type;

  /// Alias template for add_const
  template<typename _Tp>
    using add_const_t = typename add_const<_Tp>::type;

  /// Alias template for add_volatile
  template<typename _Tp>
    using add_volatile_t = typename add_volatile<_Tp>::type;

  /// Alias template for add_cv
  template<typename _Tp>
    using add_cv_t = typename add_cv<_Tp>::type;
#endif

  // Reference transformations.

  /// remove_reference
#if _GLIBCXX_USE_BUILTIN_TRAIT(__remove_reference)
  template<typename _Tp>
    struct remove_reference
    { using type = __remove_reference(_Tp); };
#else
  template<typename _Tp>
    struct remove_reference
    { using type = _Tp; };

  template<typename _Tp>
    struct remove_reference<_Tp&>
    { using type = _Tp; };

  template<typename _Tp>
    struct remove_reference<_Tp&&>
    { using type = _Tp; };
#endif

  /// add_lvalue_reference
  template<typename _Tp>
    struct add_lvalue_reference
    { using type = __add_lval_ref_t<_Tp>; };

  /// add_rvalue_reference
  template<typename _Tp>
    struct add_rvalue_reference
    { using type = __add_rval_ref_t<_Tp>; };

#if __cplusplus > 201103L
  /// Alias template for remove_reference
  template<typename _Tp>
    using remove_reference_t = typename remove_reference<_Tp>::type;

  /// Alias template for add_lvalue_reference
  template<typename _Tp>
    using add_lvalue_reference_t = typename add_lvalue_reference<_Tp>::type;

  /// Alias template for add_rvalue_reference
  template<typename _Tp>
    using add_rvalue_reference_t = typename add_rvalue_reference<_Tp>::type;
#endif

  // Sign modifications.

  /// @cond undocumented

  // Utility for constructing identically cv-qualified types.
  template<typename _Unqualified, bool _IsConst, bool _IsVol>
    struct __cv_selector;

  template<typename _Unqualified>
    struct __cv_selector<_Unqualified, false, false>
    { using __type = _Unqualified; };

  template<typename _Unqualified>
    struct __cv_selector<_Unqualified, false, true>
    { using __type = volatile _Unqualified; };

  template<typename _Unqualified>
    struct __cv_selector<_Unqualified, true, false>
    { using __type = const _Unqualified; };

  template<typename _Unqualified>
    struct __cv_selector<_Unqualified, true, true>
    { using __type = const volatile _Unqualified; };

  template<typename _Qualified, typename _Unqualified,
	   bool _IsConst = is_const<_Qualified>::value,
	   bool _IsVol = is_volatile<_Qualified>::value>
    class __match_cv_qualifiers
    {
      using __match = __cv_selector<_Unqualified, _IsConst, _IsVol>;

    public:
      using __type = typename __match::__type;
    };

  // Utility for finding the unsigned versions of signed integral types.
  template<typename _Tp>
    struct __make_unsigned
    { using __type = _Tp; };

  template<>
    struct __make_unsigned<char>
    { using __type = unsigned char; };

  template<>
    struct __make_unsigned<signed char>
    { using __type = unsigned char; };

  template<>
    struct __make_unsigned<short>
    { using __type = unsigned short; };

  template<>
    struct __make_unsigned<int>
    { using __type = unsigned int; };

  template<>
    struct __make_unsigned<long>
    { using __type = unsigned long; };

  template<>
    struct __make_unsigned<long long>
    { using __type = unsigned long long; };

#if defined(__GLIBCXX_TYPE_INT_N_0)
  __extension__
  template<>
    struct __make_unsigned<__GLIBCXX_TYPE_INT_N_0>
    { using __type = unsigned __GLIBCXX_TYPE_INT_N_0; };
#endif
#if defined(__GLIBCXX_TYPE_INT_N_1)
  __extension__
  template<>
    struct __make_unsigned<__GLIBCXX_TYPE_INT_N_1>
    { using __type = unsigned __GLIBCXX_TYPE_INT_N_1; };
#endif
#if defined(__GLIBCXX_TYPE_INT_N_2)
  __extension__
  template<>
    struct __make_unsigned<__GLIBCXX_TYPE_INT_N_2>
    { using __type = unsigned __GLIBCXX_TYPE_INT_N_2; };
#endif
#if defined(__GLIBCXX_TYPE_INT_N_3)
  __extension__
  template<>
    struct __make_unsigned<__GLIBCXX_TYPE_INT_N_3>
    { using __type = unsigned __GLIBCXX_TYPE_INT_N_3; };
#endif

  // Select between integral and enum: not possible to be both.
  template<typename _Tp,
	   bool _IsInt = is_integral<_Tp>::value,
	   bool _IsEnum = __is_enum(_Tp)>
    class __make_unsigned_selector;

  template<typename _Tp>
    class __make_unsigned_selector<_Tp, true, false>
    {
      using __unsigned_type
	= typename __make_unsigned<__remove_cv_t<_Tp>>::__type;

    public:
      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.
      using _UInts = _List<unsigned char, unsigned short, unsigned int,
			   unsigned long, unsigned long long>;

      using __unsigned_type = typename __select<sizeof(_Tp), _UInts>::__type;

    public:
      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.
  template<>
    struct __make_unsigned<wchar_t>
    {
      using __type
	= typename __make_unsigned_selector<wchar_t, false, true>::__type;
    };

#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;
    };
  /// @endcond

  // Given an integral/enum type, return the corresponding unsigned
  // integer type.
  // Primary template.
  /// make_unsigned
  template<typename _Tp>
    struct make_unsigned
    { using type = typename __make_unsigned_selector<_Tp>::__type; };

  // Integral, but don't define.
  template<> struct make_unsigned<bool>;
  template<> struct make_unsigned<bool const>;
  template<> struct make_unsigned<bool volatile>;
  template<> struct make_unsigned<bool const volatile>;

  /// @cond undocumented

  // Utility for finding the signed versions of unsigned integral types.
  template<typename _Tp>
    struct __make_signed
    { using __type = _Tp; };

  template<>
    struct __make_signed<char>
    { using __type = signed char; };

  template<>
    struct __make_signed<unsigned char>
    { using __type = signed char; };

  template<>
    struct __make_signed<unsigned short>
    { using __type = signed short; };

  template<>
    struct __make_signed<unsigned int>
    { using __type = signed int; };

  template<>
    struct __make_signed<unsigned long>
    { using __type = signed long; };

  template<>
    struct __make_signed<unsigned long long>
    { using __type = signed long long; };

#if defined(__GLIBCXX_TYPE_INT_N_0)
  __extension__
  template<>
    struct __make_signed<unsigned __GLIBCXX_TYPE_INT_N_0>
    { using __type = __GLIBCXX_TYPE_INT_N_0; };
#endif
#if defined(__GLIBCXX_TYPE_INT_N_1)
  __extension__
  template<>
    struct __make_signed<unsigned __GLIBCXX_TYPE_INT_N_1>
    { using __type = __GLIBCXX_TYPE_INT_N_1; };
#endif
#if defined(__GLIBCXX_TYPE_INT_N_2)
  __extension__
  template<>
    struct __make_signed<unsigned __GLIBCXX_TYPE_INT_N_2>
    { using __type = __GLIBCXX_TYPE_INT_N_2; };
#endif
#if defined(__GLIBCXX_TYPE_INT_N_3)
  __extension__
  template<>
    struct __make_signed<unsigned __GLIBCXX_TYPE_INT_N_3>
    { using __type = __GLIBCXX_TYPE_INT_N_3; };
#endif

  // Select between integral and enum: not possible to be both.
  template<typename _Tp,
	   bool _IsInt = is_integral<_Tp>::value,
	   bool _IsEnum = __is_enum(_Tp)>
    class __make_signed_selector;

  template<typename _Tp>
    class __make_signed_selector<_Tp, true, false>
    {
      using __signed_type
	= typename __make_signed<__remove_cv_t<_Tp>>::__type;

    public:
      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>
    {
      using __unsigned_type = typename __make_unsigned_selector<_Tp>::__type;

    public:
      using __type = typename __make_signed_selector<__unsigned_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.
  template<>
    struct __make_signed<wchar_t>
    {
      using __type
	= typename __make_signed_selector<wchar_t, false, true>::__type;
    };

#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;
    };
  /// @endcond

  // Given an integral/enum type, return the corresponding signed
  // integer type.
  // Primary template.
  /// make_signed
  template<typename _Tp>
    struct make_signed
    { using type = typename __make_signed_selector<_Tp>::__type; };

  // Integral, but don't define.
  template<> struct make_signed<bool>;
  template<> struct make_signed<bool const>;
  template<> struct make_signed<bool volatile>;
  template<> struct make_signed<bool const volatile>;

#if __cplusplus > 201103L
  /// Alias template for make_signed
  template<typename _Tp>
    using make_signed_t = typename make_signed<_Tp>::type;

  /// Alias template for make_unsigned
  template<typename _Tp>
    using make_unsigned_t = typename make_unsigned<_Tp>::type;
#endif

  // Array modifications.

  /// remove_extent
  template<typename _Tp>
    struct remove_extent
    { using type = _Tp; };

  template<typename _Tp, std::size_t _Size>
    struct remove_extent<_Tp[_Size]>
    { using type = _Tp; };

  template<typename _Tp>
    struct remove_extent<_Tp[]>
    { using type = _Tp; };

  /// remove_all_extents
  template<typename _Tp>
    struct remove_all_extents
    { using type = _Tp; };

  template<typename _Tp, std::size_t _Size>
    struct remove_all_extents<_Tp[_Size]>
    { using type = typename remove_all_extents<_Tp>::type; };

  template<typename _Tp>
    struct remove_all_extents<_Tp[]>
    { using type = typename remove_all_extents<_Tp>::type; };

#if __cplusplus > 201103L
  /// Alias template for remove_extent
  template<typename _Tp>
    using remove_extent_t = typename remove_extent<_Tp>::type;

  /// Alias template for remove_all_extents
  template<typename _Tp>
    using remove_all_extents_t = typename remove_all_extents<_Tp>::type;
#endif

  // Pointer modifications.

  /// remove_pointer
#if _GLIBCXX_USE_BUILTIN_TRAIT(__remove_pointer)
  template<typename _Tp>
    struct remove_pointer
    { using type = __remove_pointer(_Tp); };
#else
  template<typename _Tp, typename>
    struct __remove_pointer_helper
    { using type = _Tp; };

  template<typename _Tp, typename _Up>
    struct __remove_pointer_helper<_Tp, _Up*>
    { using type = _Up; };

  template<typename _Tp>
    struct remove_pointer
    : public __remove_pointer_helper<_Tp, __remove_cv_t<_Tp>>
    { };
#endif

  template<typename _Tp, typename = void>
    struct __add_pointer_helper
    { using type = _Tp; };

  template<typename _Tp>
    struct __add_pointer_helper<_Tp, __void_t<_Tp*>>
    { using type = _Tp*; };

  /// add_pointer
  template<typename _Tp>
    struct add_pointer
    : public __add_pointer_helper<_Tp>
    { };

  template<typename _Tp>
    struct add_pointer<_Tp&>
    { using type = _Tp*; };

  template<typename _Tp>
    struct add_pointer<_Tp&&>
    { using type = _Tp*; };

#if __cplusplus > 201103L
  /// Alias template for remove_pointer
  template<typename _Tp>
    using remove_pointer_t = typename remove_pointer<_Tp>::type;

  /// Alias template for add_pointer
  template<typename _Tp>
    using add_pointer_t = typename add_pointer<_Tp>::type;
#endif

  template<std::size_t _Len>
    struct __aligned_storage_msa
    {
      union __type
      {
	unsigned char __data[_Len];
	struct __attribute__((__aligned__)) { } __align;
      };
    };

  /**
   *  @brief Alignment type.
   *
   *  The value of _Align is a default-alignment which shall be the
   *  most stringent alignment requirement for any C++ object type
   *  whose size is no greater than _Len (3.9). The member typedef
   *  type shall be a POD type suitable for use as uninitialized
   *  storage for any object whose size is at most _Len and whose
   *  alignment is a divisor of _Align.
   *
   *  @deprecated Deprecated in C++23. Uses can be replaced by an
   *  array std::byte[_Len] declared with alignas(_Align).
  */
  template<std::size_t _Len, std::size_t _Align =
	   __alignof__(typename __aligned_storage_msa<_Len>::__type)>
    struct
    _GLIBCXX23_DEPRECATED
    aligned_storage
    {
      union type
      {
	unsigned char __data[_Len];
	struct __attribute__((__aligned__((_Align)))) { } __align;
      };
    };

  template <typename... _Types>
    struct __strictest_alignment
    {
      static const size_t _S_alignment = 0;
      static const size_t _S_size = 0;
    };

  template <typename _Tp, typename... _Types>
    struct __strictest_alignment<_Tp, _Types...>
    {
      static const size_t _S_alignment =
        alignof(_Tp) > __strictest_alignment<_Types...>::_S_alignment
	? alignof(_Tp) : __strictest_alignment<_Types...>::_S_alignment;
      static const size_t _S_size =
        sizeof(_Tp) > __strictest_alignment<_Types...>::_S_size
	? sizeof(_Tp) : __strictest_alignment<_Types...>::_S_size;
    };

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"

  /**
   *  @brief Provide aligned storage for types.
   *
   *  [meta.trans.other]
   *
   *  Provides aligned storage for any of the provided types of at
   *  least size _Len.
   *
   *  @see aligned_storage
   *
   *  @deprecated Deprecated in C++23.
   */
  template <size_t _Len, typename... _Types>
    struct
    _GLIBCXX23_DEPRECATED
    aligned_union
    {
    private:
      static_assert(sizeof...(_Types) != 0, "At least one type is required");

      using __strictest = __strictest_alignment<_Types...>;
      static const size_t _S_len = _Len > __strictest::_S_size
	? _Len : __strictest::_S_size;
    public:
      /// The value of the strictest alignment of _Types.
      static const size_t alignment_value = __strictest::_S_alignment;
      /// The storage.
      using type = typename aligned_storage<_S_len, alignment_value>::type;
    };

  template <size_t _Len, typename... _Types>
    const size_t aligned_union<_Len, _Types...>::alignment_value;
#pragma GCC diagnostic pop

  /// @cond undocumented

  // Decay trait for arrays and functions, used for perfect forwarding
  // in make_pair, make_tuple, etc.
  template<typename _Up>
    struct __decay_selector
    : __conditional_t<is_const<const _Up>::value, // false for functions
		      remove_cv<_Up>,		  // N.B. DR 705.
		      add_pointer<_Up>>		  // function decays to pointer
    { };

  template<typename _Up, size_t _Nm>
    struct __decay_selector<_Up[_Nm]>
    { using type = _Up*; };

  template<typename _Up>
    struct __decay_selector<_Up[]>
    { using type = _Up*; };

  /// @endcond

  /// decay
  template<typename _Tp>
    struct decay
    { using type = typename __decay_selector<_Tp>::type; };

  template<typename _Tp>
    struct decay<_Tp&>
    { using type = typename __decay_selector<_Tp>::type; };

  template<typename _Tp>
    struct decay<_Tp&&>
    { using type = typename __decay_selector<_Tp>::type; };

  /// @cond undocumented

  // Helper which adds a reference to a type when given a reference_wrapper
  template<typename _Tp>
    struct __strip_reference_wrapper
    {
      using __type = _Tp;
    };

  template<typename _Tp>
    struct __strip_reference_wrapper<reference_wrapper<_Tp> >
    {
      using __type = _Tp&;
    };

  // __decay_t (std::decay_t for C++11).
  template<typename _Tp>
    using __decay_t = typename decay<_Tp>::type;

  template<typename _Tp>
    using __decay_and_strip = __strip_reference_wrapper<__decay_t<_Tp>>;
  /// @endcond

  /// @cond undocumented

  // Helper for SFINAE constraints
  template<typename... _Cond>
    using _Require = __enable_if_t<__and_<_Cond...>::value>;

  // __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;
  /// @endcond

  // Primary template.
  /// Define a member typedef @c type to one of two argument types.
  template<bool _Cond, typename _Iftrue, typename _Iffalse>
    struct conditional
    { using type = _Iftrue; };

  // Partial specialization for false.
  template<typename _Iftrue, typename _Iffalse>
    struct conditional<false, _Iftrue, _Iffalse>
    { using type = _Iffalse; };

  /// common_type
  template<typename... _Tp>
    struct common_type;

  // Sfinae-friendly common_type implementation:

  /// @cond undocumented

  // 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
  // that, because we need to derive from them as an implementation detail.

  template<typename _Tp>
    struct __success_type
    { using type = _Tp; };

  struct __failure_type
  { };

  struct __do_common_type_impl
  {
    template<typename _Tp, typename _Up>
      using __cond_t
	= decltype(true ? std::declval<_Tp>() : std::declval<_Up>());

    // if decay_t<decltype(false ? declval<D1>() : declval<D2>())>
    // denotes a valid type, let C denote that type.
    template<typename _Tp, typename _Up>
      static __success_type<__decay_t<__cond_t<_Tp, _Up>>>
      _S_test(int);

#if __cplusplus > 201703L
    // Otherwise, if COND-RES(CREF(D1), CREF(D2)) denotes a type,
    // let C denote the type decay_t<COND-RES(CREF(D1), CREF(D2))>.
    template<typename _Tp, typename _Up>
      static __success_type<__remove_cvref_t<__cond_t<const _Tp&, const _Up&>>>
      _S_test_2(int);
#endif

    template<typename, typename>
      static __failure_type
      _S_test_2(...);

    template<typename _Tp, typename _Up>
      static decltype(_S_test_2<_Tp, _Up>(0))
      _S_test(...);
  };

  // If sizeof...(T) is zero, there shall be no member type.
  template<>
    struct common_type<>
    { };

  // 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>
    { };

  // If sizeof...(T) is two, ...
  template<typename _Tp1, typename _Tp2,
	   typename _Dp1 = __decay_t<_Tp1>, typename _Dp2 = __decay_t<_Tp2>>
    struct __common_type_impl
    {
      // 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 _Tp1, typename _Tp2>
    struct __common_type_impl<_Tp1, _Tp2, _Tp1, _Tp2>
    : private __do_common_type_impl
    {
      // 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));
    };

  // 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, typename, typename = void>
    struct __common_type_fold;

  // 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...>
    { };

  // 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)>
    struct __underlying_type_impl
    {
      using type = __underlying_type(_Tp);
    };

  template<typename _Tp>
    struct __underlying_type_impl<_Tp, false>
    { };
  /// @endcond

  /// The underlying type of an enum.
  template<typename _Tp>
    struct underlying_type
    : public __underlying_type_impl<_Tp>
    { };

  /// @cond undocumented
  template<typename _Tp>
    struct __declval_protector
    {
      static const bool __stop = false;
    };
  /// @endcond

  /** Utility to simplify expressions used in unevaluated operands
   *  @since C++11
   *  @ingroup utilities
   */
  template<typename _Tp>
    auto declval() noexcept -> decltype(__declval<_Tp>(0))
    {
      static_assert(__declval_protector<_Tp>::__stop,
		    "declval() must not be used!");
      return __declval<_Tp>(0);
    }

  /// result_of
  template<typename _Signature>
    struct result_of;

  // Sfinae-friendly result_of implementation:

  /// @cond undocumented
  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 __result_of_success<decltype(
      (std::declval<_Tp1>().*std::declval<_Fp>())(std::declval<_Args>()...)
      ), __invoke_memfun_ref> _S_test(int);

    template<typename...>
      static __failure_type _S_test(...);
  };

  template<typename _MemPtr, typename _Arg, typename... _Args>
    struct __result_of_memfun_ref
    : private __result_of_memfun_ref_impl
    {
      using type = decltype(_S_test<_MemPtr, _Arg, _Args...>(0));
    };

  // [func.require] paragraph 1 bullet 2:
  struct __result_of_memfun_deref_impl
  {
    template<typename _Fp, typename _Tp1, typename... _Args>
      static __result_of_success<decltype(
      ((*std::declval<_Tp1>()).*std::declval<_Fp>())(std::declval<_Args>()...)
      ), __invoke_memfun_deref> _S_test(int);

    template<typename...>
      static __failure_type _S_test(...);
  };

  template<typename _MemPtr, typename _Arg, typename... _Args>
    struct __result_of_memfun_deref
    : private __result_of_memfun_deref_impl
    {
      using type = decltype(_S_test<_MemPtr, _Arg, _Args...>(0));
    };

  // [func.require] paragraph 1 bullet 3:
  struct __result_of_memobj_ref_impl
  {
    template<typename _Fp, typename _Tp1>
      static __result_of_success<decltype(
      std::declval<_Tp1>().*std::declval<_Fp>()
      ), __invoke_memobj_ref> _S_test(int);

    template<typename, typename>
      static __failure_type _S_test(...);
  };

  template<typename _MemPtr, typename _Arg>
    struct __result_of_memobj_ref
    : private __result_of_memobj_ref_impl
    {
      using type = decltype(_S_test<_MemPtr, _Arg>(0));
    };

  // [func.require] paragraph 1 bullet 4:
  struct __result_of_memobj_deref_impl
  {
    template<typename _Fp, typename _Tp1>
      static __result_of_success<decltype(
      (*std::declval<_Tp1>()).*std::declval<_Fp>()
      ), __invoke_memobj_deref> _S_test(int);

    template<typename, typename>
      static __failure_type _S_test(...);
  };

  template<typename _MemPtr, typename _Arg>
    struct __result_of_memobj_deref
    : private __result_of_memobj_deref_impl
    {
      using type = decltype(_S_test<_MemPtr, _Arg>(0));
    };

  template<typename _MemPtr, typename _Arg>
    struct __result_of_memobj;

  template<typename _Res, typename _Class, typename _Arg>
    struct __result_of_memobj<_Res _Class::*, _Arg>
    {
      using _Argval = __remove_cvref_t<_Arg>;
      using _MemPtr = _Res _Class::*;
      using type = typename __conditional_t<__or_<is_same<_Argval, _Class>,
        is_base_of<_Class, _Argval>>::value,
        __result_of_memobj_ref<_MemPtr, _Arg>,
        __result_of_memobj_deref<_MemPtr, _Arg>
      >::type;
    };

  template<typename _MemPtr, typename _Arg, typename... _Args>
    struct __result_of_memfun;

  template<typename _Res, typename _Class, typename _Arg, typename... _Args>
    struct __result_of_memfun<_Res _Class::*, _Arg, _Args...>
    {
      using _Argval = typename remove_reference<_Arg>::type;
      using _MemPtr = _Res _Class::*;
      using type = typename __conditional_t<is_base_of<_Class, _Argval>::value,
        __result_of_memfun_ref<_MemPtr, _Arg, _Args...>,
        __result_of_memfun_deref<_MemPtr, _Arg, _Args...>
      >::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
    {
      using type = __failure_type;
    };

  template<typename _MemPtr, typename _Arg>
    struct __result_of_impl<true, false, _MemPtr, _Arg>
    : public __result_of_memobj<__decay_t<_MemPtr>,
				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<__decay_t<_MemPtr>,
				typename __inv_unwrap<_Arg>::type, _Args...>
    { };

  // [func.require] paragraph 1 bullet 5:
  struct __result_of_other_impl
  {
    template<typename _Fn, typename... _Args>
      static __result_of_success<decltype(
      std::declval<_Fn>()(std::declval<_Args>()...)
      ), __invoke_other> _S_test(int);

    template<typename...>
      static __failure_type _S_test(...);
  };

  template<typename _Functor, typename... _ArgTypes>
    struct __result_of_impl<false, false, _Functor, _ArgTypes...>
    : private __result_of_other_impl
    {
      using type = decltype(_S_test<_Functor, _ArgTypes...>(0));
    };

  // __invoke_result (std::invoke_result for C++11)
  template<typename _Functor, typename... _ArgTypes>
    struct __invoke_result
    : public __result_of_impl<
        is_member_object_pointer<
          typename remove_reference<_Functor>::type
        >::value,
        is_member_function_pointer<
          typename remove_reference<_Functor>::type
        >::value,
	_Functor, _ArgTypes...
      >::type
    { };

  // __invoke_result_t (std::invoke_result_t for C++11)
  template<typename _Fn, typename... _Args>
    using __invoke_result_t = typename __invoke_result<_Fn, _Args...>::type;
  /// @endcond

  template<typename _Functor, typename... _ArgTypes>
    struct result_of<_Functor(_ArgTypes...)>
    : public __invoke_result<_Functor, _ArgTypes...>
    { } _GLIBCXX17_DEPRECATED_SUGGEST("std::invoke_result");

#if __cplusplus >= 201402L
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
  /// Alias template for aligned_storage
  template<size_t _Len, size_t _Align =
	    __alignof__(typename __aligned_storage_msa<_Len>::__type)>
    using aligned_storage_t _GLIBCXX23_DEPRECATED = typename aligned_storage<_Len, _Align>::type;

  template <size_t _Len, typename... _Types>
    using aligned_union_t _GLIBCXX23_DEPRECATED = typename aligned_union<_Len, _Types...>::type;
#pragma GCC diagnostic pop

  /// Alias template for decay
  template<typename _Tp>
    using decay_t = typename decay<_Tp>::type;

  /// Alias template for enable_if
  template<bool _Cond, typename _Tp = void>
    using enable_if_t = typename enable_if<_Cond, _Tp>::type;

  /// Alias template for conditional
  template<bool _Cond, typename _Iftrue, typename _Iffalse>
    using conditional_t = typename conditional<_Cond, _Iftrue, _Iffalse>::type;

  /// Alias template for common_type
  template<typename... _Tp>
    using common_type_t = typename common_type<_Tp...>::type;

  /// Alias template for underlying_type
  template<typename _Tp>
    using underlying_type_t = typename underlying_type<_Tp>::type;

  /// Alias template for result_of
  template<typename _Tp>
    using result_of_t = typename result_of<_Tp>::type;
#endif // C++14

#ifdef __cpp_lib_void_t // C++ >= 17 || GNU++ >= 11
  /// A metafunction that always yields void, used for detecting valid types.
  template<typename...> using void_t = void;
#endif

  /// @cond undocumented

  // Detection idiom.
  // Detect whether _Op<_Args...> is a valid type, use default _Def if not.

#if __cpp_concepts
  // Implementation of the detection idiom (negative case).
  template<typename _Def, template<typename...> class _Op, typename... _Args>
    struct __detected_or
    {
      using type = _Def;
      using __is_detected = false_type;
    };

  // Implementation of the detection idiom (positive case).
  template<typename _Def, template<typename...> class _Op, typename... _Args>
    requires requires { typename _Op<_Args...>; }
    struct __detected_or<_Def, _Op, _Args...>
    {
      using type = _Op<_Args...>;
      using __is_detected = true_type;
    };
#else
  /// Implementation of the detection idiom (negative case).
  template<typename _Default, typename _AlwaysVoid,
	   template<typename...> class _Op, typename... _Args>
    struct __detector
    {
      using type = _Default;
      using __is_detected = false_type;
    };

  /// 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 type = _Op<_Args...>;
      using __is_detected = true_type;
    };

  template<typename _Default, template<typename...> class _Op,
	   typename... _Args>
    using __detected_or = __detector<_Default, void, _Op, _Args...>;
#endif // __cpp_concepts

  // _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;

  /**
   *  Use SFINAE to determine if the type _Tp has a publicly-accessible
   *  member type _NTYPE.
   */
#define _GLIBCXX_HAS_NESTED_TYPE(_NTYPE)				\
  template<typename _Tp, typename = __void_t<>>				\
    struct __has_##_NTYPE						\
    : false_type							\
    { };								\
  template<typename _Tp>						\
    struct __has_##_NTYPE<_Tp, __void_t<typename _Tp::_NTYPE>>		\
    : true_type								\
    { };

  template <typename _Tp>
    struct __is_swappable;

  template <typename _Tp>
    struct __is_nothrow_swappable;

  template<typename>
    struct __is_tuple_like_impl : false_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
    { };
  /// @endcond

  template<typename _Tp>
    _GLIBCXX20_CONSTEXPR
    inline
    _Require<__not_<__is_tuple_like<_Tp>>,
	     is_move_constructible<_Tp>,
	     is_move_assignable<_Tp>>
    swap(_Tp&, _Tp&)
    noexcept(__and_<is_nothrow_move_constructible<_Tp>,
	            is_nothrow_move_assignable<_Tp>>::value);

  template<typename _Tp, size_t _Nm>
    _GLIBCXX20_CONSTEXPR
    inline
    __enable_if_t<__is_swappable<_Tp>::value>
    swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm])
    noexcept(__is_nothrow_swappable<_Tp>::value);

  /// @cond undocumented
  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
    {
      using type = decltype(__test<_Tp>(0));
    };

  template<typename _Tp>
    struct __is_nothrow_swappable_impl
    : public __swappable_details::__do_is_nothrow_swappable_impl
    {
      using type = decltype(__test<_Tp>(0));
    };

  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
    { };
  /// @endcond

#ifdef __cpp_lib_is_swappable // C++ >= 17 || GNU++ >= 11
  /// 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

  /// @cond undocumented
  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
    {
      using type = decltype(__test<_Tp, _Up>(0));
    };

  // 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
    {
      using type = decltype(__test<_Tp&>(0));
    };

  template<typename _Tp, typename _Up>
    struct __is_nothrow_swappable_with_impl
    : public __swappable_with_details::__do_is_nothrow_swappable_with_impl
    {
      using type = decltype(__test<_Tp, _Up>(0));
    };

  // 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
    {
      using type = decltype(__test<_Tp&>(0));
    };
  /// @endcond

  /// is_swappable_with
  template<typename _Tp, typename _Up>
    struct is_swappable_with
    : public __is_swappable_with_impl<_Tp, _Up>::type
    {
      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
	"first template argument must be a complete class or an unbounded array");
      static_assert(std::__is_complete_or_unbounded(__type_identity<_Up>{}),
	"second template argument must be a complete class or an unbounded array");
    };

  /// is_nothrow_swappable_with
  template<typename _Tp, typename _Up>
    struct is_nothrow_swappable_with
    : public __is_nothrow_swappable_with_impl<_Tp, _Up>::type
    {
      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
	"first template argument must be a complete class or an unbounded array");
      static_assert(std::__is_complete_or_unbounded(__type_identity<_Up>{}),
	"second template argument must be a complete class or an unbounded array");
    };

#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 // __cpp_lib_is_swappable

  /// @cond undocumented

  // __is_invocable (std::is_invocable for C++11)

  // The primary template is used for invalid INVOKE expressions.
  template<typename _Result, typename _Ret,
	   bool = is_void<_Ret>::value, typename = void>
    struct __is_invocable_impl
    : false_type
    {
      using __nothrow_conv = false_type; // For is_nothrow_invocable_r
    };

  // Used for valid INVOKE and INVOKE<void> expressions.
  template<typename _Result, typename _Ret>
    struct __is_invocable_impl<_Result, _Ret,
			       /* is_void<_Ret> = */ true,
			       __void_t<typename _Result::type>>
    : true_type
    {
      using __nothrow_conv = true_type; // For is_nothrow_invocable_r
    };

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
  // Used for INVOKE<R> expressions to check the implicit conversion to R.
  template<typename _Result, typename _Ret>
    struct __is_invocable_impl<_Result, _Ret,
			       /* is_void<_Ret> = */ false,
			       __void_t<typename _Result::type>>
    {
    private:
      // The type of the INVOKE expression.
      using _Res_t = typename _Result::type;

      // Unlike declval, this doesn't add_rvalue_reference, so it respects
      // guaranteed copy elision.
      static _Res_t _S_get() noexcept;

      // Used to check if _Res_t can implicitly convert to _Tp.
      template<typename _Tp>
	static void _S_conv(__type_identity_t<_Tp>) noexcept;

      // This overload is viable if INVOKE(f, args...) can convert to _Tp.
      template<typename _Tp,
	       bool _Nothrow = noexcept(_S_conv<_Tp>(_S_get())),
	       typename = decltype(_S_conv<_Tp>(_S_get())),
#if __has_builtin(__reference_converts_from_temporary)
	       bool _Dangle = __reference_converts_from_temporary(_Tp, _Res_t)
#else
	       bool _Dangle = false
#endif
	      >
	static __bool_constant<_Nothrow && !_Dangle>
	_S_test(int);

      template<typename _Tp, bool = false>
	static false_type
	_S_test(...);

    public:
      // For is_invocable_r
      using type = decltype(_S_test<_Ret, /* Nothrow = */ true>(1));

      // For is_nothrow_invocable_r
      using __nothrow_conv = decltype(_S_test<_Ret>(1));
    };
#pragma GCC diagnostic pop

  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
  /// @endcond

#ifdef __cpp_lib_is_invocable // C++ >= 17
  /// std::invoke_result
  template<typename _Functor, typename... _ArgTypes>
    struct invoke_result
    : public __invoke_result<_Functor, _ArgTypes...>
    {
      static_assert(std::__is_complete_or_unbounded(__type_identity<_Functor>{}),
	"_Functor must be a complete class or an unbounded array");
      static_assert((std::__is_complete_or_unbounded(
	__type_identity<_ArgTypes>{}) && ...),
	"each argument type must be a complete class or an unbounded array");
    };

  /// 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");
      static_assert((std::__is_complete_or_unbounded(
	__type_identity<_ArgTypes>{}) && ...),
	"each argument type 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");
      static_assert((std::__is_complete_or_unbounded(
	__type_identity<_ArgTypes>{}) && ...),
	"each argument type must be a complete class or an unbounded array");
      static_assert(std::__is_complete_or_unbounded(__type_identity<_Ret>{}),
	"_Ret 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");
      static_assert((std::__is_complete_or_unbounded(
	__type_identity<_ArgTypes>{}) && ...),
	"each argument type must be a complete class or an unbounded array");
    };

  /// @cond undocumented
  // This checks that the INVOKE<R> expression is well-formed and that the
  // conversion to R does not throw. It does *not* check whether the INVOKE
  // expression itself can throw. That is done by __call_is_nothrow_ instead.
  template<typename _Result, typename _Ret>
    using __is_nt_invocable_impl
      = typename __is_invocable_impl<_Result, _Ret>::__nothrow_conv;
  /// @endcond

  /// 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
    {
      static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}),
	"_Fn must be a complete class or an unbounded array");
      static_assert((std::__is_complete_or_unbounded(
	__type_identity<_ArgTypes>{}) && ...),
	"each argument type must be a complete class or an unbounded array");
      static_assert(std::__is_complete_or_unbounded(__type_identity<_Ret>{}),
	"_Ret must be a complete class or an unbounded array");
    };
#endif // __cpp_lib_is_invocable

#if __cpp_lib_type_trait_variable_templates // C++ >= 17
  /**
   * @defgroup variable_templates Variable templates for type traits
   * @ingroup metaprogramming
   *
   * Each variable `is_xxx_v<T>` is a boolean constant with the same value
   * as the `value` member of the corresponding type trait `is_xxx<T>`.
   *
   * @since C++17 unless noted otherwise.
   */

  /**
   * @{
   * @ingroup variable_templates
   */
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;

#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_array)
template <typename _Tp>
  inline constexpr bool is_array_v = __is_array(_Tp);
#else
template <typename _Tp>
  inline constexpr bool is_array_v = false;
template <typename _Tp>
  inline constexpr bool is_array_v<_Tp[]> = true;
template <typename _Tp, size_t _Num>
  inline constexpr bool is_array_v<_Tp[_Num]> = true;
#endif

template <typename _Tp>
  inline constexpr bool is_pointer_v = is_pointer<_Tp>::value;
template <typename _Tp>
  inline constexpr bool is_lvalue_reference_v = false;
template <typename _Tp>
  inline constexpr bool is_lvalue_reference_v<_Tp&> = true;
template <typename _Tp>
  inline constexpr bool is_rvalue_reference_v = false;
template <typename _Tp>
  inline constexpr bool is_rvalue_reference_v<_Tp&&> = true;

#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_member_object_pointer)
template <typename _Tp>
  inline constexpr bool is_member_object_pointer_v =
    __is_member_object_pointer(_Tp);
#else
template <typename _Tp>
  inline constexpr bool is_member_object_pointer_v =
    is_member_object_pointer<_Tp>::value;
#endif

#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_member_function_pointer)
template <typename _Tp>
  inline constexpr bool is_member_function_pointer_v =
    __is_member_function_pointer(_Tp);
#else
template <typename _Tp>
  inline constexpr bool is_member_function_pointer_v =
    is_member_function_pointer<_Tp>::value;
#endif

template <typename _Tp>
  inline constexpr bool is_enum_v = __is_enum(_Tp);
template <typename _Tp>
  inline constexpr bool is_union_v = __is_union(_Tp);
template <typename _Tp>
  inline constexpr bool is_class_v = __is_class(_Tp);
// is_function_v is defined below, after is_const_v.

#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_reference)
template <typename _Tp>
  inline constexpr bool is_reference_v = __is_reference(_Tp);
#else
template <typename _Tp>
  inline constexpr bool is_reference_v = false;
template <typename _Tp>
  inline constexpr bool is_reference_v<_Tp&> = true;
template <typename _Tp>
  inline constexpr bool is_reference_v<_Tp&&> = true;
#endif

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;

#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_object)
template <typename _Tp>
  inline constexpr bool is_object_v = __is_object(_Tp);
#else
template <typename _Tp>
  inline constexpr bool is_object_v = is_object<_Tp>::value;
#endif

template <typename _Tp>
  inline constexpr bool is_scalar_v = is_scalar<_Tp>::value;
template <typename _Tp>
  inline constexpr bool is_compound_v = !is_fundamental_v<_Tp>;

#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_member_pointer)
template <typename _Tp>
  inline constexpr bool is_member_pointer_v = __is_member_pointer(_Tp);
#else
template <typename _Tp>
  inline constexpr bool is_member_pointer_v = is_member_pointer<_Tp>::value;
#endif

template <typename _Tp>
  inline constexpr bool is_const_v = false;
template <typename _Tp>
  inline constexpr bool is_const_v<const _Tp> = true;

#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_function)
template <typename _Tp>
  inline constexpr bool is_function_v = __is_function(_Tp);
#else
template <typename _Tp>
  inline constexpr bool is_function_v = !is_const_v<const _Tp>;
template <typename _Tp>
  inline constexpr bool is_function_v<_Tp&> = false;
template <typename _Tp>
  inline constexpr bool is_function_v<_Tp&&> = false;
#endif

template <typename _Tp>
  inline constexpr bool is_volatile_v = false;
template <typename _Tp>
  inline constexpr bool is_volatile_v<volatile _Tp> = true;

template <typename _Tp>
  inline constexpr bool is_trivial_v = __is_trivial(_Tp);
template <typename _Tp>
  inline constexpr bool is_trivially_copyable_v = __is_trivially_copyable(_Tp);
template <typename _Tp>
  inline constexpr bool is_standard_layout_v = __is_standard_layout(_Tp);
template <typename _Tp>
  _GLIBCXX20_DEPRECATED_SUGGEST("is_standard_layout_v && is_trivial_v")
  inline constexpr bool is_pod_v = __is_pod(_Tp);
template <typename _Tp>
  _GLIBCXX17_DEPRECATED
  inline constexpr bool is_literal_type_v = __is_literal_type(_Tp);
template <typename _Tp>
  inline constexpr bool is_empty_v = __is_empty(_Tp);
template <typename _Tp>
  inline constexpr bool is_polymorphic_v = __is_polymorphic(_Tp);
template <typename _Tp>
  inline constexpr bool is_abstract_v = __is_abstract(_Tp);
template <typename _Tp>
  inline constexpr bool is_final_v = __is_final(_Tp);

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...);
template <typename _Tp>
  inline constexpr bool is_default_constructible_v = __is_constructible(_Tp);
template <typename _Tp>
  inline constexpr bool is_copy_constructible_v
    = __is_constructible(_Tp, __add_lval_ref_t<const _Tp>);
template <typename _Tp>
  inline constexpr bool is_move_constructible_v
    = __is_constructible(_Tp, __add_rval_ref_t<_Tp>);

template <typename _Tp, typename _Up>
  inline constexpr bool is_assignable_v = __is_assignable(_Tp, _Up);
template <typename _Tp>
  inline constexpr bool is_copy_assignable_v
    = __is_assignable(__add_lval_ref_t<_Tp>, __add_lval_ref_t<const _Tp>);
template <typename _Tp>
  inline constexpr bool is_move_assignable_v
    = __is_assignable(__add_lval_ref_t<_Tp>, __add_rval_ref_t<_Tp>);

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...);
template <typename _Tp>
  inline constexpr bool is_trivially_default_constructible_v
    = __is_trivially_constructible(_Tp);
template <typename _Tp>
  inline constexpr bool is_trivially_copy_constructible_v
    = __is_trivially_constructible(_Tp, __add_lval_ref_t<const _Tp>);
template <typename _Tp>
  inline constexpr bool is_trivially_move_constructible_v
    = __is_trivially_constructible(_Tp, __add_rval_ref_t<_Tp>);

template <typename _Tp, typename _Up>
  inline constexpr bool is_trivially_assignable_v
    = __is_trivially_assignable(_Tp, _Up);
template <typename _Tp>
  inline constexpr bool is_trivially_copy_assignable_v
    = __is_trivially_assignable(__add_lval_ref_t<_Tp>,
				__add_lval_ref_t<const _Tp>);
template <typename _Tp>
  inline constexpr bool is_trivially_move_assignable_v
    = __is_trivially_assignable(__add_lval_ref_t<_Tp>,
				__add_rval_ref_t<_Tp>);

#if __cpp_concepts
template <typename _Tp>
  inline constexpr bool is_trivially_destructible_v = false;

template <typename _Tp>
  requires (!is_reference_v<_Tp>) && requires (_Tp& __t) { __t.~_Tp(); }
  inline constexpr bool is_trivially_destructible_v<_Tp>
    = __has_trivial_destructor(_Tp);
template <typename _Tp>
  inline constexpr bool is_trivially_destructible_v<_Tp&> = true;
template <typename _Tp>
  inline constexpr bool is_trivially_destructible_v<_Tp&&> = true;
template <typename _Tp, size_t _Nm>
  inline constexpr bool is_trivially_destructible_v<_Tp[_Nm]>
    = is_trivially_destructible_v<_Tp>;
#else
template <typename _Tp>
  inline constexpr bool is_trivially_destructible_v =
    is_trivially_destructible<_Tp>::value;
#endif

template <typename _Tp, typename... _Args>
  inline constexpr bool is_nothrow_constructible_v
    = __is_nothrow_constructible(_Tp, _Args...);
template <typename _Tp>
  inline constexpr bool is_nothrow_default_constructible_v
    = __is_nothrow_constructible(_Tp);
template <typename _Tp>
  inline constexpr bool is_nothrow_copy_constructible_v
    = __is_nothrow_constructible(_Tp, __add_lval_ref_t<const _Tp>);
template <typename _Tp>
  inline constexpr bool is_nothrow_move_constructible_v
    = __is_nothrow_constructible(_Tp, __add_rval_ref_t<_Tp>);

template <typename _Tp, typename _Up>
  inline constexpr bool is_nothrow_assignable_v
    = __is_nothrow_assignable(_Tp, _Up);
template <typename _Tp>
  inline constexpr bool is_nothrow_copy_assignable_v
    = __is_nothrow_assignable(__add_lval_ref_t<_Tp>,
			      __add_lval_ref_t<const _Tp>);
template <typename _Tp>
  inline constexpr bool is_nothrow_move_assignable_v
    = __is_nothrow_assignable(__add_lval_ref_t<_Tp>, __add_rval_ref_t<_Tp>);

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);

template <typename _Tp>
  inline constexpr size_t alignment_of_v = alignment_of<_Tp>::value;

template <typename _Tp>
  inline constexpr size_t rank_v = 0;
template <typename _Tp, size_t _Size>
  inline constexpr size_t rank_v<_Tp[_Size]> = 1 + rank_v<_Tp>;
template <typename _Tp>
  inline constexpr size_t rank_v<_Tp[]> = 1 + rank_v<_Tp>;

template <typename _Tp, unsigned _Idx = 0>
  inline constexpr size_t extent_v = 0;
template <typename _Tp, size_t _Size>
  inline constexpr size_t extent_v<_Tp[_Size], 0> = _Size;
template <typename _Tp, unsigned _Idx, size_t _Size>
  inline constexpr size_t extent_v<_Tp[_Size], _Idx> = extent_v<_Tp, _Idx - 1>;
template <typename _Tp>
  inline constexpr size_t extent_v<_Tp[], 0> = 0;
template <typename _Tp, unsigned _Idx>
  inline constexpr size_t extent_v<_Tp[], _Idx> = extent_v<_Tp, _Idx - 1>;

#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_same)
template <typename _Tp, typename _Up>
  inline constexpr bool is_same_v = __is_same(_Tp, _Up);
#else
template <typename _Tp, typename _Up>
  inline constexpr bool is_same_v = false;
template <typename _Tp>
  inline constexpr bool is_same_v<_Tp, _Tp> = true;
#endif
template <typename _Base, typename _Derived>
  inline constexpr bool is_base_of_v = __is_base_of(_Base, _Derived);
#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_convertible)
template <typename _From, typename _To>
  inline constexpr bool is_convertible_v = __is_convertible(_From, _To);
#else
template <typename _From, typename _To>
  inline constexpr bool is_convertible_v = is_convertible<_From, _To>::value;
#endif
template<typename _Fn, typename... _Args>
  inline constexpr bool is_invocable_v = is_invocable<_Fn, _Args...>::value;
template<typename _Fn, typename... _Args>
  inline constexpr bool is_nothrow_invocable_v
    = is_nothrow_invocable<_Fn, _Args...>::value;
template<typename _Ret, typename _Fn, typename... _Args>
  inline constexpr bool is_invocable_r_v
    = is_invocable_r<_Ret, _Fn, _Args...>::value;
template<typename _Ret, typename _Fn, typename... _Args>
  inline constexpr bool is_nothrow_invocable_r_v
    = is_nothrow_invocable_r<_Ret, _Fn, _Args...>::value;
/// @}
#endif // __cpp_lib_type_trait_variable_templates

#ifdef __cpp_lib_has_unique_object_representations // C++ >= 17 && HAS_UNIQ_OBJ_REP
  /// has_unique_object_representations
  /// @since C++17
  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");
    };

# if __cpp_lib_type_trait_variable_templates // C++ >= 17
  /// @ingroup variable_templates
  template<typename _Tp>
    inline constexpr bool has_unique_object_representations_v
      = has_unique_object_representations<_Tp>::value;
# endif
#endif

#ifdef __cpp_lib_is_aggregate // C++ >= 17 && builtin_is_aggregate
  /// is_aggregate - true if the type is an aggregate.
  /// @since C++17
  template<typename _Tp>
    struct is_aggregate
    : bool_constant<__is_aggregate(remove_cv_t<_Tp>)>
    { };

# if __cpp_lib_type_trait_variable_templates // C++ >= 17
  /** is_aggregate_v - true if the type is an aggregate.
   *  @ingroup variable_templates
   *  @since C++17
   */
  template<typename _Tp>
    inline constexpr bool is_aggregate_v = __is_aggregate(remove_cv_t<_Tp>);
# endif
#endif

  /** * Remove references and cv-qualifiers.
   * @since C++20
   * @{
   */
#ifdef __cpp_lib_remove_cvref // C++ >= 20
# if _GLIBCXX_USE_BUILTIN_TRAIT(__remove_cvref)
  template<typename _Tp>
    struct remove_cvref
    { using type = __remove_cvref(_Tp); };
# else
  template<typename _Tp>
    struct remove_cvref
    { using type = typename remove_cv<_Tp>::type; };

  template<typename _Tp>
    struct remove_cvref<_Tp&>
    { using type = typename remove_cv<_Tp>::type; };

  template<typename _Tp>
    struct remove_cvref<_Tp&&>
    { using type = typename remove_cv<_Tp>::type; };
# endif

  template<typename _Tp>
    using remove_cvref_t = typename remove_cvref<_Tp>::type;
  /// @}
#endif // __cpp_lib_remove_cvref

#ifdef __cpp_lib_type_identity // C++ >= 20
  /** * Identity metafunction.
   * @since C++20
   * @{
   */
  template<typename _Tp>
    struct type_identity { using type = _Tp; };

  template<typename _Tp>
    using type_identity_t = typename type_identity<_Tp>::type;
  /// @}
#endif

#ifdef __cpp_lib_unwrap_ref // C++ >= 20
  /** Unwrap a reference_wrapper
   * @since C++20
   * @{
   */
  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
   * @since C++20
   * @{
   */
  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;
  /// @}
#endif // __cpp_lib_unwrap_ref

#ifdef __cpp_lib_bounded_array_traits // C++ >= 20
  /// True for a type that is an array of known bound.
  /// @ingroup variable_templates
  /// @since C++20
# if _GLIBCXX_USE_BUILTIN_TRAIT(__is_bounded_array)
  template<typename _Tp>
    inline constexpr bool is_bounded_array_v = __is_bounded_array(_Tp);
# else
  template<typename _Tp>
    inline constexpr bool is_bounded_array_v = false;

  template<typename _Tp, size_t _Size>
    inline constexpr bool is_bounded_array_v<_Tp[_Size]> = true;
# endif

  /// True for a type that is an array of unknown bound.
  /// @ingroup variable_templates
  /// @since C++20
  template<typename _Tp>
    inline constexpr bool is_unbounded_array_v = false;

  template<typename _Tp>
    inline constexpr bool is_unbounded_array_v<_Tp[]> = true;

  /// True for a type that is an array of known bound.
  /// @since C++20
  template<typename _Tp>
    struct is_bounded_array
    : public bool_constant<is_bounded_array_v<_Tp>>
    { };

  /// True for a type that is an array of unknown bound.
  /// @since C++20
  template<typename _Tp>
    struct is_unbounded_array
    : public bool_constant<is_unbounded_array_v<_Tp>>
    { };
#endif // __cpp_lib_bounded_array_traits

#if __has_builtin(__is_layout_compatible) && __cplusplus >= 202002L

  /// @since C++20
  template<typename _Tp, typename _Up>
    struct is_layout_compatible
    : bool_constant<__is_layout_compatible(_Tp, _Up)>
    { };

  /// @ingroup variable_templates
  /// @since C++20
  template<typename _Tp, typename _Up>
    constexpr bool is_layout_compatible_v
      = __is_layout_compatible(_Tp, _Up);

#if __has_builtin(__builtin_is_corresponding_member)
# ifndef __cpp_lib_is_layout_compatible
#  error "libstdc++ bug: is_corresponding_member and is_layout_compatible are provided but their FTM is not set"
# endif

  /// @since C++20
  template<typename _S1, typename _S2, typename _M1, typename _M2>
    constexpr bool
    is_corresponding_member(_M1 _S1::*__m1, _M2 _S2::*__m2) noexcept
    { return __builtin_is_corresponding_member(__m1, __m2); }
#endif
#endif

#if __has_builtin(__is_pointer_interconvertible_base_of) \
  && __cplusplus >= 202002L
  /// True if `_Derived` is standard-layout and has a base class of type `_Base`
  /// @since C++20
  template<typename _Base, typename _Derived>
    struct is_pointer_interconvertible_base_of
    : bool_constant<__is_pointer_interconvertible_base_of(_Base, _Derived)>
    { };

  /// @ingroup variable_templates
  /// @since C++20
  template<typename _Base, typename _Derived>
    constexpr bool is_pointer_interconvertible_base_of_v
      = __is_pointer_interconvertible_base_of(_Base, _Derived);

#if __has_builtin(__builtin_is_pointer_interconvertible_with_class)
# ifndef __cpp_lib_is_pointer_interconvertible
#  error "libstdc++ bug: is_pointer_interconvertible available but FTM is not set"
# endif

  /// True if `__mp` points to the first member of a standard-layout type
  /// @returns true if `s.*__mp` is pointer-interconvertible with `s`
  /// @since C++20
  template<typename _Tp, typename _Mem>
    constexpr bool
    is_pointer_interconvertible_with_class(_Mem _Tp::*__mp) noexcept
    { return __builtin_is_pointer_interconvertible_with_class(__mp); }
#endif
#endif

#ifdef __cpp_lib_is_scoped_enum // C++ >= 23
  /// True if the type is a scoped enumeration type.
  /// @since C++23

# if _GLIBCXX_USE_BUILTIN_TRAIT(__is_scoped_enum)
  template<typename _Tp>
    struct is_scoped_enum
    : bool_constant<__is_scoped_enum(_Tp)>
    { };
# else
  template<typename _Tp>
    struct is_scoped_enum
    : false_type
    { };

  template<typename _Tp>
    requires __is_enum(_Tp)
    && requires(remove_cv_t<_Tp> __t) { __t = __t; } // fails if incomplete
    struct is_scoped_enum<_Tp>
    : bool_constant<!requires(_Tp __t, void(*__f)(int)) { __f(__t); }>
    { };
# endif

  /// @ingroup variable_templates
  /// @since C++23
# if _GLIBCXX_USE_BUILTIN_TRAIT(__is_scoped_enum)
  template<typename _Tp>
    inline constexpr bool is_scoped_enum_v = __is_scoped_enum(_Tp);
# else
  template<typename _Tp>
    inline constexpr bool is_scoped_enum_v = is_scoped_enum<_Tp>::value;
# endif
#endif

#ifdef __cpp_lib_reference_from_temporary // C++ >= 23 && ref_{converts,constructs}_from_temp
  /// True if _Tp is a reference type, a _Up value can be bound to _Tp in
  /// direct-initialization, and a temporary object would be bound to
  /// the reference, false otherwise.
  /// @since C++23
  template<typename _Tp, typename _Up>
    struct reference_constructs_from_temporary
    : public bool_constant<__reference_constructs_from_temporary(_Tp, _Up)>
    {
      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{})
		    && std::__is_complete_or_unbounded(__type_identity<_Up>{}),
	"template argument must be a complete class or an unbounded array");
    };

  /// True if _Tp is a reference type, a _Up value can be bound to _Tp in
  /// copy-initialization, and a temporary object would be bound to
  /// the reference, false otherwise.
  /// @since C++23
  template<typename _Tp, typename _Up>
    struct reference_converts_from_temporary
    : public bool_constant<__reference_converts_from_temporary(_Tp, _Up)>
    {
      static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{})
		    && std::__is_complete_or_unbounded(__type_identity<_Up>{}),
	"template argument must be a complete class or an unbounded array");
    };

  /// @ingroup variable_templates
  /// @since C++23
  template<typename _Tp, typename _Up>
    inline constexpr bool reference_constructs_from_temporary_v
      = reference_constructs_from_temporary<_Tp, _Up>::value;

  /// @ingroup variable_templates
  /// @since C++23
  template<typename _Tp, typename _Up>
    inline constexpr bool reference_converts_from_temporary_v
      = reference_converts_from_temporary<_Tp, _Up>::value;
#endif // __cpp_lib_reference_from_temporary

#ifdef __cpp_lib_is_constant_evaluated // C++ >= 20 && HAVE_IS_CONST_EVAL
  /// Returns true only when called during constant evaluation.
  /// @since C++20
  constexpr inline bool
  is_constant_evaluated() noexcept
  {
#if __cpp_if_consteval >= 202106L
    if consteval { return true; } else { return false; }
#else
    return __builtin_is_constant_evaluated();
#endif
  }
#endif

#if __cplusplus >= 202002L
  /// @cond undocumented
  template<typename _From, typename _To>
    using __copy_cv = typename __match_cv_qualifiers<_From, _To>::__type;

  template<typename _Xp, typename _Yp>
    using __cond_res
      = decltype(false ? declval<_Xp(&)()>()() : declval<_Yp(&)()>()());

  template<typename _Ap, typename _Bp, typename = void>
    struct __common_ref_impl
    { };

  // [meta.trans.other], COMMON-REF(A, B)
  template<typename _Ap, typename _Bp>
    using __common_ref = typename __common_ref_impl<_Ap, _Bp>::type;

  // COND-RES(COPYCV(X, Y) &, COPYCV(Y, X) &)
  template<typename _Xp, typename _Yp>
    using __condres_cvref
      = __cond_res<__copy_cv<_Xp, _Yp>&, __copy_cv<_Yp, _Xp>&>;

  // If A and B are both lvalue reference types, ...
  template<typename _Xp, typename _Yp>
    struct __common_ref_impl<_Xp&, _Yp&, __void_t<__condres_cvref<_Xp, _Yp>>>
    : enable_if<is_reference_v<__condres_cvref<_Xp, _Yp>>,
		__condres_cvref<_Xp, _Yp>>
    { };

  // let C be remove_reference_t<COMMON-REF(X&, Y&)>&&
  template<typename _Xp, typename _Yp>
    using __common_ref_C = remove_reference_t<__common_ref<_Xp&, _Yp&>>&&;

  // If A and B are both rvalue reference types, ...
  template<typename _Xp, typename _Yp>
    struct __common_ref_impl<_Xp&&, _Yp&&,
      _Require<is_convertible<_Xp&&, __common_ref_C<_Xp, _Yp>>,
	       is_convertible<_Yp&&, __common_ref_C<_Xp, _Yp>>>>
    { using type = __common_ref_C<_Xp, _Yp>; };

  // let D be COMMON-REF(const X&, Y&)
  template<typename _Xp, typename _Yp>
    using __common_ref_D = __common_ref<const _Xp&, _Yp&>;

  // If A is an rvalue reference and B is an lvalue reference, ...
  template<typename _Xp, typename _Yp>
    struct __common_ref_impl<_Xp&&, _Yp&,
      _Require<is_convertible<_Xp&&, __common_ref_D<_Xp, _Yp>>>>
    { using type = __common_ref_D<_Xp, _Yp>; };

  // If A is an lvalue reference and B is an rvalue reference, ...
  template<typename _Xp, typename _Yp>
    struct __common_ref_impl<_Xp&, _Yp&&>
    : __common_ref_impl<_Yp&&, _Xp&>
    { };
  /// @endcond

  template<typename _Tp, typename _Up,
	   template<typename> class _TQual, template<typename> class _UQual>
    struct basic_common_reference
    { };

  /// @cond undocumented
  template<typename _Tp>
    struct __xref
    { template<typename _Up> using __type = __copy_cv<_Tp, _Up>; };

  template<typename _Tp>
    struct __xref<_Tp&>
    { template<typename _Up> using __type = __copy_cv<_Tp, _Up>&; };

  template<typename _Tp>
    struct __xref<_Tp&&>
    { template<typename _Up> using __type = __copy_cv<_Tp, _Up>&&; };

  template<typename _Tp1, typename _Tp2>
    using __basic_common_ref
      = typename basic_common_reference<remove_cvref_t<_Tp1>,
					remove_cvref_t<_Tp2>,
					__xref<_Tp1>::template __type,
					__xref<_Tp2>::template __type>::type;
  /// @endcond

  template<typename... _Tp>
    struct common_reference;

  template<typename... _Tp>
    using common_reference_t = typename common_reference<_Tp...>::type;

  // If sizeof...(T) is zero, there shall be no member type.
  template<>
    struct common_reference<>
    { };

  // If sizeof...(T) is one ...
  template<typename _Tp0>
    struct common_reference<_Tp0>
    { using type = _Tp0; };

  /// @cond undocumented
  template<typename _Tp1, typename _Tp2, int _Bullet = 1, typename = void>
    struct __common_reference_impl
    : __common_reference_impl<_Tp1, _Tp2, _Bullet + 1>
    { };

  // If sizeof...(T) is two ...
  template<typename _Tp1, typename _Tp2>
    struct common_reference<_Tp1, _Tp2>
    : __common_reference_impl<_Tp1, _Tp2>
    { };

  // If T1 and T2 are reference types and COMMON-REF(T1, T2) is well-formed, ...
  template<typename _Tp1, typename _Tp2>
    struct __common_reference_impl<_Tp1&, _Tp2&, 1,
				   void_t<__common_ref<_Tp1&, _Tp2&>>>
    { using type = __common_ref<_Tp1&, _Tp2&>; };

  template<typename _Tp1, typename _Tp2>
    struct __common_reference_impl<_Tp1&&, _Tp2&&, 1,
				   void_t<__common_ref<_Tp1&&, _Tp2&&>>>
    { using type = __common_ref<_Tp1&&, _Tp2&&>; };

  template<typename _Tp1, typename _Tp2>
    struct __common_reference_impl<_Tp1&, _Tp2&&, 1,
				   void_t<__common_ref<_Tp1&, _Tp2&&>>>
    { using type = __common_ref<_Tp1&, _Tp2&&>; };

  template<typename _Tp1, typename _Tp2>
    struct __common_reference_impl<_Tp1&&, _Tp2&, 1,
				   void_t<__common_ref<_Tp1&&, _Tp2&>>>
    { using type = __common_ref<_Tp1&&, _Tp2&>; };

  // Otherwise, if basic_common_reference<...>::type is well-formed, ...
  template<typename _Tp1, typename _Tp2>
    struct __common_reference_impl<_Tp1, _Tp2, 2,
				   void_t<__basic_common_ref<_Tp1, _Tp2>>>
    { using type = __basic_common_ref<_Tp1, _Tp2>; };

  // Otherwise, if COND-RES(T1, T2) is well-formed, ...
  template<typename _Tp1, typename _Tp2>
    struct __common_reference_impl<_Tp1, _Tp2, 3,
				   void_t<__cond_res<_Tp1, _Tp2>>>
    { using type = __cond_res<_Tp1, _Tp2>; };

  // Otherwise, if common_type_t<T1, T2> is well-formed, ...
  template<typename _Tp1, typename _Tp2>
    struct __common_reference_impl<_Tp1, _Tp2, 4,
				   void_t<common_type_t<_Tp1, _Tp2>>>
    { using type = common_type_t<_Tp1, _Tp2>; };

  // Otherwise, there shall be no member type.
  template<typename _Tp1, typename _Tp2>
    struct __common_reference_impl<_Tp1, _Tp2, 5, void>
    { };

  // Otherwise, if sizeof...(T) is greater than two, ...
  template<typename _Tp1, typename _Tp2, typename... _Rest>
    struct common_reference<_Tp1, _Tp2, _Rest...>
    : __common_type_fold<common_reference<_Tp1, _Tp2>,
			 __common_type_pack<_Rest...>>
    { };

  // Reuse __common_type_fold for common_reference<T1, T2, Rest...>
  template<typename _Tp1, typename _Tp2, typename... _Rest>
    struct __common_type_fold<common_reference<_Tp1, _Tp2>,
			      __common_type_pack<_Rest...>,
			      void_t<common_reference_t<_Tp1, _Tp2>>>
    : public common_reference<common_reference_t<_Tp1, _Tp2>, _Rest...>
    { };
  /// @endcond

#endif // C++2a

  /// @} group metaprogramming

_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std

#endif  // C++11

#endif  // _GLIBCXX_TYPE_TRAITS
