// C++0x type_traits -*- C++ -*-

// Copyright (C) 2007, 2008, 2009, 2010 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

#ifndef __GXX_EXPERIMENTAL_CXX0X__
# include <bits/c++0x_warning.h>
#else

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

namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION

  /**
   * @addtogroup metaprogramming
   * @{
   */
  struct __sfinae_types
  {
    typedef char __one;
    typedef struct { char __arr[2]; } __two;
  };

#define _DEFINE_SPEC_0_HELPER                          \
  template<>

#define _DEFINE_SPEC_1_HELPER                          \
  template<typename _Tp>

#define _DEFINE_SPEC_2_HELPER                          \
  template<typename _Tp, typename _Cp>

#define _DEFINE_SPEC(_Order, _Trait, _Type, _Value)    \
  _DEFINE_SPEC_##_Order##_HELPER                       \
    struct _Trait<_Type>                               \
    : public integral_constant<bool, _Value> { };

  // helper classes.

  /// integral_constant
  template<typename _Tp, _Tp __v>
    struct integral_constant
    {
      static constexpr _Tp                  value = __v;
      typedef _Tp                           value_type;
      typedef integral_constant<_Tp, __v>   type;
      constexpr operator value_type() { return value; }
    };
  
  /// typedef for true_type
  typedef integral_constant<bool, true>     true_type;

  /// typedef for false_type
  typedef integral_constant<bool, false>    false_type;

  template<typename _Tp, _Tp __v>
    constexpr _Tp integral_constant<_Tp, __v>::value;

  /// remove_cv
  template<typename>
    struct remove_cv;

  template<typename>
    struct __is_void_helper
    : public false_type { };
  _DEFINE_SPEC(0, __is_void_helper, void, true)

  // primary type categories.

  /// is_void
  template<typename _Tp>
    struct is_void
    : public integral_constant<bool, (__is_void_helper<typename
				      remove_cv<_Tp>::type>::value)>
    { };

  template<typename>
    struct __is_integral_helper
    : public false_type { };
  _DEFINE_SPEC(0, __is_integral_helper, bool, true)
  _DEFINE_SPEC(0, __is_integral_helper, char, true)
  _DEFINE_SPEC(0, __is_integral_helper, signed char, true)
  _DEFINE_SPEC(0, __is_integral_helper, unsigned char, true)
#ifdef _GLIBCXX_USE_WCHAR_T
  _DEFINE_SPEC(0, __is_integral_helper, wchar_t, true)
#endif
  _DEFINE_SPEC(0, __is_integral_helper, char16_t, true)
  _DEFINE_SPEC(0, __is_integral_helper, char32_t, true)
  _DEFINE_SPEC(0, __is_integral_helper, short, true)
  _DEFINE_SPEC(0, __is_integral_helper, unsigned short, true)
  _DEFINE_SPEC(0, __is_integral_helper, int, true)
  _DEFINE_SPEC(0, __is_integral_helper, unsigned int, true)
  _DEFINE_SPEC(0, __is_integral_helper, long, true)
  _DEFINE_SPEC(0, __is_integral_helper, unsigned long, true)
  _DEFINE_SPEC(0, __is_integral_helper, long long, true)
  _DEFINE_SPEC(0, __is_integral_helper, unsigned long long, true)

  /// is_integral
  template<typename _Tp>
    struct is_integral
    : public integral_constant<bool, (__is_integral_helper<typename
				      remove_cv<_Tp>::type>::value)>
    { };

  template<typename>
    struct __is_floating_point_helper
    : public false_type { };
  _DEFINE_SPEC(0, __is_floating_point_helper, float, true)
  _DEFINE_SPEC(0, __is_floating_point_helper, double, true)
  _DEFINE_SPEC(0, __is_floating_point_helper, long double, true)

  /// is_floating_point
  template<typename _Tp>
    struct is_floating_point
    : public integral_constant<bool, (__is_floating_point_helper<typename
				      remove_cv<_Tp>::type>::value)>
    { };

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

  template<typename>
    struct __is_pointer_helper
    : public false_type { };
  _DEFINE_SPEC(1, __is_pointer_helper, _Tp*, true)

  /// is_pointer
  template<typename _Tp>
    struct is_pointer
    : public integral_constant<bool, (__is_pointer_helper<typename
				      remove_cv<_Tp>::type>::value)>
    { };

  /// is_reference
  template<typename _Tp>
    struct is_reference;

  /// is_function
  template<typename _Tp>
    struct is_function;

  template<typename>
    struct __is_member_object_pointer_helper
    : public false_type { };
  _DEFINE_SPEC(2, __is_member_object_pointer_helper, _Tp _Cp::*,
	       !is_function<_Tp>::value)

  /// is_member_object_pointer
  template<typename _Tp>
    struct is_member_object_pointer
    : public integral_constant<bool, (__is_member_object_pointer_helper<
				      typename remove_cv<_Tp>::type>::value)>
    { };

  template<typename>
    struct __is_member_function_pointer_helper
    : public false_type { };
  _DEFINE_SPEC(2, __is_member_function_pointer_helper, _Tp _Cp::*,
	       is_function<_Tp>::value)

  /// is_member_function_pointer
  template<typename _Tp>
    struct is_member_function_pointer
    : public integral_constant<bool, (__is_member_function_pointer_helper<
				      typename remove_cv<_Tp>::type>::value)>
    { };

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

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

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

  /// is_function
  template<typename>
    struct is_function
    : public false_type { };
  template<typename _Res, typename... _ArgTypes>
    struct is_function<_Res(_ArgTypes...)>
    : public true_type { };
  template<typename _Res, typename... _ArgTypes>
    struct is_function<_Res(_ArgTypes......)>
    : public true_type { };
  template<typename _Res, typename... _ArgTypes>
    struct is_function<_Res(_ArgTypes...) const>
    : public true_type { };
  template<typename _Res, typename... _ArgTypes>
    struct is_function<_Res(_ArgTypes......) const>
    : public true_type { };
  template<typename _Res, typename... _ArgTypes>
    struct is_function<_Res(_ArgTypes...) volatile>
    : public true_type { };
  template<typename _Res, typename... _ArgTypes>
    struct is_function<_Res(_ArgTypes......) volatile>
    : public true_type { };
  template<typename _Res, typename... _ArgTypes>
    struct is_function<_Res(_ArgTypes...) const volatile>
    : public true_type { };
  template<typename _Res, typename... _ArgTypes>
    struct is_function<_Res(_ArgTypes......) const volatile>
    : public true_type { };

  template<typename>
    struct __is_nullptr_t_helper
    : public false_type { };
  _DEFINE_SPEC(0, __is_nullptr_t_helper, std::nullptr_t, true)

  // __is_nullptr_t (extension).
  template<typename _Tp>
    struct __is_nullptr_t
    : public integral_constant<bool, (__is_nullptr_t_helper<typename
				      remove_cv<_Tp>::type>::value)>
    { };

  // composite type traits.
  
  /// is_arithmetic
  template<typename _Tp>
    struct is_arithmetic
    : public integral_constant<bool, (is_integral<_Tp>::value
				      || is_floating_point<_Tp>::value)>
    { };

  /// is_fundamental
  template<typename _Tp>
    struct is_fundamental
    : public integral_constant<bool, (is_arithmetic<_Tp>::value
				      || is_void<_Tp>::value)>
    { };

  /// is_object
  template<typename _Tp>
    struct is_object
    : public integral_constant<bool, !(is_function<_Tp>::value
				       || is_reference<_Tp>::value
				       || is_void<_Tp>::value)>
    { };

  /// is_member_pointer
  template<typename _Tp>
    struct is_member_pointer;

  /// is_scalar
  template<typename _Tp>
    struct is_scalar
    : public integral_constant<bool, (is_arithmetic<_Tp>::value
				      || is_enum<_Tp>::value
				      || is_pointer<_Tp>::value
				      || is_member_pointer<_Tp>::value
				      || __is_nullptr_t<_Tp>::value)>
    { };

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

  /// is_member_pointer
  template<typename _Tp>
    struct __is_member_pointer_helper
    : public false_type { };
  _DEFINE_SPEC(2, __is_member_pointer_helper, _Tp _Cp::*, true)

  template<typename _Tp>
  struct is_member_pointer
    : public integral_constant<bool, (__is_member_pointer_helper<
				      typename remove_cv<_Tp>::type>::value)>
    { };

  // 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_empty
  template<typename _Tp>
    struct is_empty
    : public integral_constant<bool, __is_empty(_Tp)>
    { };

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

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

  /// has_virtual_destructor
  template<typename _Tp>
    struct has_virtual_destructor
    : public integral_constant<bool, __has_virtual_destructor(_Tp)>
    { };

  /// alignment_of
  template<typename _Tp>
    struct alignment_of
    : public integral_constant<std::size_t, __alignof__(_Tp)> { };
  
  /// 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<std::size_t, 0> { };
  
  template<typename _Tp, unsigned _Uint, std::size_t _Size>
    struct extent<_Tp[_Size], _Uint>
    : public integral_constant<std::size_t,
			       _Uint == 0 ? _Size : extent<_Tp,
							   _Uint - 1>::value>
    { };

  template<typename _Tp, unsigned _Uint>
    struct extent<_Tp[], _Uint>
    : public integral_constant<std::size_t,
			       _Uint == 0 ? 0 : extent<_Tp,
						       _Uint - 1>::value>
    { };

  // relationships between types [4.6].

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

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

  // const-volatile modifications [4.7.1].

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

  template<typename _Tp>
    struct remove_const<_Tp const>
    { typedef _Tp     type; };
  
  /// remove_volatile
  template<typename _Tp>
    struct remove_volatile
    { typedef _Tp     type; };

  template<typename _Tp>
    struct remove_volatile<_Tp volatile>
    { typedef _Tp     type; };
  
  /// remove_cv
  template<typename _Tp>
    struct remove_cv
    {
      typedef typename
      remove_const<typename remove_volatile<_Tp>::type>::type     type;
    };
  
  /// add_const
  template<typename _Tp>
    struct add_const
    { typedef _Tp const     type; };
   
  /// add_volatile
  template<typename _Tp>
    struct add_volatile
    { typedef _Tp volatile     type; };
  
  /// add_cv
  template<typename _Tp>
    struct add_cv
    {
      typedef typename
      add_const<typename add_volatile<_Tp>::type>::type     type;
    };

  // array modifications.

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

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

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

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

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

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

  // pointer modifications.

  template<typename _Tp, typename>
    struct __remove_pointer_helper
    { typedef _Tp     type; };

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

  /// remove_pointer
  template<typename _Tp>
    struct remove_pointer
    : public __remove_pointer_helper<_Tp, typename remove_cv<_Tp>::type>
    { };

  template<typename>
    struct remove_reference;

  /// add_pointer
  template<typename _Tp>
    struct add_pointer
    { typedef typename remove_reference<_Tp>::type*     type; };

  // Primary classification traits.

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

  // Secondary classification traits.

  /// is_reference
  template<typename _Tp>
    struct is_reference
    : public integral_constant<bool, (is_lvalue_reference<_Tp>::value
				      || is_rvalue_reference<_Tp>::value)>
    { };

  // Reference transformations.

  /// remove_reference
  template<typename _Tp>
    struct remove_reference
    { typedef _Tp   type; };

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

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

  template<typename _Tp,
	   bool = !is_reference<_Tp>::value && !is_void<_Tp>::value,
	   bool = is_rvalue_reference<_Tp>::value>
    struct __add_lvalue_reference_helper
    { typedef _Tp   type; };

  template<typename _Tp>
    struct __add_lvalue_reference_helper<_Tp, true, false>
    { typedef _Tp&   type; };

  template<typename _Tp>
    struct __add_lvalue_reference_helper<_Tp, false, true>
    { typedef typename remove_reference<_Tp>::type&   type; };

  /// add_lvalue_reference
  template<typename _Tp>
    struct add_lvalue_reference
    : public __add_lvalue_reference_helper<_Tp>
    { };

  template<typename _Tp,
	   bool = !is_reference<_Tp>::value && !is_void<_Tp>::value>
    struct __add_rvalue_reference_helper
    { typedef _Tp   type; };

  template<typename _Tp>
    struct __add_rvalue_reference_helper<_Tp, true>
    { typedef _Tp&&   type; };

  /// add_rvalue_reference
  template<typename _Tp>
    struct add_rvalue_reference
    : public __add_rvalue_reference_helper<_Tp>
    { };

  // Scalar properties and transformations.

  template<typename _Tp,
	   bool = is_integral<_Tp>::value,
	   bool = is_floating_point<_Tp>::value>
    struct __is_signed_helper
    : public false_type { };

  template<typename _Tp>
    struct __is_signed_helper<_Tp, false, true>
    : public true_type { };

  template<typename _Tp>
    struct __is_signed_helper<_Tp, true, false>
    : public integral_constant<bool, static_cast<bool>(_Tp(-1) < _Tp(0))>
    { };

  /// is_signed
  template<typename _Tp>
    struct is_signed
    : public integral_constant<bool, __is_signed_helper<_Tp>::value>
    { };

  /// is_unsigned
  template<typename _Tp>
    struct is_unsigned
    : public integral_constant<bool, (is_arithmetic<_Tp>::value
				      && !is_signed<_Tp>::value)>
    { };

  // Member introspection.

  /// is_trivial
  template<typename _Tp>
    struct is_trivial
    : public integral_constant<bool, __is_trivial(_Tp)>
    { };

  /// is_standard_layout
  template<typename _Tp>
    struct is_standard_layout
    : public integral_constant<bool, __is_standard_layout(_Tp)>
    { };

  /// is_pod
  // Could use is_standard_layout && is_trivial instead of the builtin.
  template<typename _Tp>
    struct is_pod
    : public integral_constant<bool, __is_pod(_Tp)>
    { };

  /// is_literal_type
  template<typename _Tp>
    struct is_literal_type
    : public integral_constant<bool, __is_literal_type(_Tp)>
    { };

  template<typename _Tp>
    typename add_rvalue_reference<_Tp>::type declval() noexcept;

  template<typename _Tp, typename... _Args>
    class __is_constructible_helper
    : public __sfinae_types
    {
      template<typename _Tp1, typename... _Args1>
        static decltype(_Tp1(declval<_Args1>()...), __one()) __test(int);

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

    public:
      static const bool __value = sizeof(__test<_Tp, _Args...>(0)) == 1;
    };

  template<typename _Tp, typename _Arg>
    class __is_constructible_helper<_Tp, _Arg>
    : public __sfinae_types
    {
      template<typename _Tp1, typename _Arg1>
        static decltype(static_cast<_Tp1>(declval<_Arg1>()), __one())
	__test(int);

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

    public:
      static const bool __value = sizeof(__test<_Tp, _Arg>(0)) == 1;
    };

  /// is_constructible
  // XXX FIXME
  // The C++0x specifications require front-end support, see N2255.
  template<typename _Tp, typename... _Args>
    struct is_constructible
    : public integral_constant<bool,
			       __is_constructible_helper<_Tp,
							 _Args...>::__value>
    { };

  template<bool, typename _Tp, typename... _Args>
    struct __is_nt_constructible_helper
    { static const bool __value = false; };

  template<typename _Tp, typename... _Args>
    struct __is_nt_constructible_helper<true, _Tp, _Args...>
    { static const bool __value = noexcept(_Tp(declval<_Args>()...)); };

  template<typename _Tp, typename _Arg>
    struct __is_nt_constructible_helper<true, _Tp, _Arg>
    {
      static const bool __value = noexcept(static_cast<_Tp>(declval<_Arg>()));
    };

  /// is_nothrow_constructible
  template<typename _Tp, typename... _Args>
    struct is_nothrow_constructible
    : public integral_constant<bool,
	  __is_nt_constructible_helper<is_constructible<_Tp, _Args...>::value,
				       _Tp, _Args...>::__value>
    { };

  /// has_trivial_default_constructor
  template<typename _Tp>
    struct has_trivial_default_constructor
    : public integral_constant<bool, __has_trivial_constructor(_Tp)>
    { };

  /// has_trivial_copy_constructor
  template<typename _Tp>
    struct has_trivial_copy_constructor
    : public integral_constant<bool, __has_trivial_copy(_Tp)>
    { };

  /// has_trivial_copy_assign
  template<typename _Tp>
    struct has_trivial_copy_assign
    : public integral_constant<bool, __has_trivial_assign(_Tp)>
    { };

  /// has_trivial_destructor
  template<typename _Tp>
    struct has_trivial_destructor
    : public integral_constant<bool, __has_trivial_destructor(_Tp)>
    { };

  /// has_nothrow_default_constructor
  template<typename _Tp>
    struct has_nothrow_default_constructor
    : public integral_constant<bool, __has_nothrow_constructor(_Tp)>
    { };

  /// has_nothrow_copy_constructor
  template<typename _Tp>
    struct has_nothrow_copy_constructor
    : public integral_constant<bool, __has_nothrow_copy(_Tp)>
    { };

  /// has_nothrow_copy_assign
  template<typename _Tp>
    struct has_nothrow_copy_assign
    : public integral_constant<bool, __has_nothrow_assign(_Tp)>
    { };

  // Relationships between types.

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

  template<typename _From, typename _To,
	   bool = (is_void<_From>::value || is_function<_To>::value
		   || is_array<_To>::value)>
    struct __is_convertible_helper
    { static const bool __value = is_void<_To>::value; };

  template<typename _From, typename _To>
    class __is_convertible_helper<_From, _To, false>
    : public __sfinae_types
    {
      template<typename _To1>
        static void __test_aux(_To1);

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

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

    public:
      static const bool __value = sizeof(__test<_From, _To>(0)) == 1;
    };

  /// is_convertible
  // XXX FIXME
  // The C++0x specifications require front-end support, see N2255.
  template<typename _From, typename _To>
    struct is_convertible
    : public integral_constant<bool,
			       __is_convertible_helper<_From, _To>::__value>
    { };

  /// is_explicitly_convertible
  template<typename _From, typename _To>
    struct is_explicitly_convertible
    : public is_constructible<_To, _From>
    { };

  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.
  */
  template<std::size_t _Len, std::size_t _Align =
	   __alignof__(typename __aligned_storage_msa<_Len>::__type)>
    struct aligned_storage
    { 
      union type
      {
	unsigned char __data[_Len];
	struct __attribute__((__aligned__((_Align)))) { } __align; 
      };
    };


  // Define a nested type if some predicate holds.
  // Primary template.
  /// enable_if
  template<bool, typename _Tp = void>
    struct enable_if 
    { };

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


  // A conditional expression, but for types. If true, first, if false, second.
  // Primary template.
  /// conditional
  template<bool _Cond, typename _Iftrue, typename _Iffalse>
    struct conditional
    { typedef _Iftrue type; };

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


  // Decay trait for arrays and functions, used for perfect forwarding
  // in make_pair, make_tuple, etc.
  template<typename _Up, 
	   bool _IsArray = is_array<_Up>::value,
	   bool _IsFunction = is_function<_Up>::value> 
    struct __decay_selector;

  // NB: DR 705.
  template<typename _Up> 
    struct __decay_selector<_Up, false, false>
    { typedef typename remove_cv<_Up>::type __type; };

  template<typename _Up> 
    struct __decay_selector<_Up, true, false>
    { typedef typename remove_extent<_Up>::type* __type; };

  template<typename _Up> 
    struct __decay_selector<_Up, false, true>
    { typedef typename add_pointer<_Up>::type __type; };

  /// decay
  template<typename _Tp> 
    class decay 
    { 
      typedef typename remove_reference<_Tp>::type __remove_type;

    public:
      typedef typename __decay_selector<__remove_type>::__type type;
    };

  template<typename _Tp>
    class reference_wrapper;

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

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

  template<typename _Tp>
    struct __strip_reference_wrapper<const reference_wrapper<_Tp> >
    {
      typedef _Tp& __type;
    };

  template<typename _Tp>
    struct __decay_and_strip
    {
      typedef typename __strip_reference_wrapper<
	typename decay<_Tp>::type>::__type __type;
    };


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

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

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

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

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

    public:
      typedef typename __match::__type __type; 
    };


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

  template<>
    struct __make_unsigned<char>
    { typedef unsigned char __type; };

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

  template<>
    struct __make_unsigned<short>
    { typedef unsigned short __type; };

  template<>
    struct __make_unsigned<int>
    { typedef unsigned int __type; };

  template<>
    struct __make_unsigned<long>
    { typedef unsigned long __type; };

  template<>
    struct __make_unsigned<long long>
    { typedef unsigned long long __type; };


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

  template<typename _Tp>
    class __make_unsigned_selector<_Tp, true, false>
    {
      typedef __make_unsigned<typename remove_cv<_Tp>::type> __unsignedt;
      typedef typename __unsignedt::__type __unsigned_type;
      typedef __match_cv_qualifiers<_Tp, __unsigned_type> __cv_unsigned;

    public:
      typedef typename __cv_unsigned::__type __type;
    };

  template<typename _Tp>
    class __make_unsigned_selector<_Tp, false, true>
    {
      // With -fshort-enums, an enum may be as small as a char.
      typedef unsigned char __smallest;
      static const bool __b0 = sizeof(_Tp) <= sizeof(__smallest);
      static const bool __b1 = sizeof(_Tp) <= sizeof(unsigned short);
      static const bool __b2 = sizeof(_Tp) <= sizeof(unsigned int);
      typedef conditional<__b2, unsigned int, unsigned long> __cond2;
      typedef typename __cond2::type __cond2_type;
      typedef conditional<__b1, unsigned short, __cond2_type> __cond1;
      typedef typename __cond1::type __cond1_type;

    public:
      typedef typename conditional<__b0, __smallest, __cond1_type>::type __type;
    };

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

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


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

  template<>
    struct __make_signed<char>
    { typedef signed char __type; };

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

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

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

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

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


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

  template<typename _Tp>
    class __make_signed_selector<_Tp, true, false>
    {
      typedef __make_signed<typename remove_cv<_Tp>::type> __signedt;
      typedef typename __signedt::__type __signed_type;
      typedef __match_cv_qualifiers<_Tp, __signed_type> __cv_signed;

    public:
      typedef typename __cv_signed::__type __type;
    };

  template<typename _Tp>
    class __make_signed_selector<_Tp, false, true>
    {
      // With -fshort-enums, an enum may be as small as a char.
      typedef signed char __smallest;
      static const bool __b0 = sizeof(_Tp) <= sizeof(__smallest);
      static const bool __b1 = sizeof(_Tp) <= sizeof(signed short);
      static const bool __b2 = sizeof(_Tp) <= sizeof(signed int);
      typedef conditional<__b2, signed int, signed long> __cond2;
      typedef typename __cond2::type __cond2_type;
      typedef conditional<__b1, signed short, __cond2_type> __cond1;
      typedef typename __cond1::type __cond1_type;

    public:
      typedef typename conditional<__b0, __smallest, __cond1_type>::type __type;
    };

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

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

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

  template<typename _Tp>
    struct common_type<_Tp>
    { typedef _Tp type; };

  template<typename _Tp, typename _Up>
    struct common_type<_Tp, _Up>
    { typedef decltype(true ? declval<_Tp>() : declval<_Up>()) type; };

  template<typename _Tp, typename _Up, typename... _Vp>
    struct common_type<_Tp, _Up, _Vp...>
    {
      typedef typename
        common_type<typename common_type<_Tp, _Up>::type, _Vp...>::type type;
    };

  /// declval
  template<typename _Tp>
    struct __declval_protector
    {
      static const bool __stop = false;
      static typename add_rvalue_reference<_Tp>::type __delegate();
    };

  template<typename _Tp>
    inline typename add_rvalue_reference<_Tp>::type
    declval() noexcept
    {
      static_assert(__declval_protector<_Tp>::__stop,
		    "declval() must not be used!");
      return __declval_protector<_Tp>::__delegate();
    }

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

  template<typename _MemPtr, typename _Arg>
    struct _Result_of_memobj;

  template<typename _Res, typename _Class, typename _Arg>
    struct _Result_of_memobj<_Res _Class::*, _Arg>
    {
    private:
      typedef _Res _Class::* _Func;

      template<typename _Tp>
	static _Tp _S_get(const _Class&);
      template<typename _Tp>
	static decltype(*std::declval<_Tp>()) _S_get(...);
        
    public:
      typedef
        decltype(_S_get<_Arg>(std::declval<_Arg>()).*std::declval<_Func>())
        __type;
    };

  template<typename _MemPtr, typename _Arg, typename... _ArgTypes>
    struct _Result_of_memfun;

  template<typename _Res, typename _Class, typename _Arg, typename... _Args>
    struct _Result_of_memfun<_Res _Class::*, _Arg, _Args...>
    {
    private:
      typedef _Res _Class::* _Func;

      template<typename _Tp>
	static _Tp _S_get(const _Class&);
      template<typename _Tp>
	static decltype(*std::declval<_Tp>()) _S_get(...);
        
    public:
      typedef
        decltype((_S_get<_Arg>(std::declval<_Arg>()).*std::declval<_Func>())
            (std::declval<_Args>()...) )
        __type;
    };

  template<bool, bool, typename _Functor, typename... _ArgTypes>
    struct _Result_of_impl;

  template<typename _Functor, typename... _ArgTypes>
    struct _Result_of_impl<false, false, _Functor, _ArgTypes...>
    {
      typedef
        decltype( std::declval<_Functor>()(std::declval<_ArgTypes>()...) )
        __type;
    };

  template<typename _MemPtr, typename _Arg>
    struct _Result_of_impl<true, false, _MemPtr, _Arg>
    : _Result_of_memobj<typename remove_reference<_MemPtr>::type, _Arg>
    {
      typedef typename _Result_of_memobj<
	typename remove_reference<_MemPtr>::type, _Arg>::__type
	__type;
    };

  template<typename _MemPtr, typename _Arg, typename... _ArgTypes>
    struct _Result_of_impl<false, true, _MemPtr, _Arg, _ArgTypes...>
    : _Result_of_memfun<typename remove_reference<_MemPtr>::type, _Arg,
                        _ArgTypes...>
    {
      typedef typename _Result_of_memfun<
	typename remove_reference<_MemPtr>::type, _Arg, _ArgTypes...>::__type
	__type;
    };

  template<typename _Functor, typename... _ArgTypes>
    struct result_of<_Functor(_ArgTypes...)>
    : _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...>
    {
      typedef typename _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
	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>                                         \
    class __has_##_NTYPE##_helper                                \
    : __sfinae_types                                             \
    {                                                            \
      template<typename _Up>                                     \
        struct _Wrap_type                                        \
	{ };                                                     \
                                                                 \
      template<typename _Up>                                     \
        static __one __test(_Wrap_type<typename _Up::_NTYPE>*);  \
                                                                 \
      template<typename _Up>                                     \
        static __two __test(...);                                \
                                                                 \
    public:                                                      \
      static const bool value = sizeof(__test<_Tp>(0)) == 1;     \
    };                                                           \
                                                                 \
  template<typename _Tp>                                         \
    struct __has_##_NTYPE                                        \
    : integral_constant<bool, __has_##_NTYPE##_helper            \
			<typename remove_cv<_Tp>::type>::value>  \
    { };

#undef _DEFINE_SPEC_0_HELPER
#undef _DEFINE_SPEC_1_HELPER
#undef _DEFINE_SPEC_2_HELPER
#undef _DEFINE_SPEC

  // @} group metaprogramming
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace

#endif  // __GXX_EXPERIMENTAL_CXX0X__

#endif  // _GLIBCXX_TYPE_TRAITS
