// TR1 type_traits -*- C++ -*-

// Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
// 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 tr1/type_traits
 *  This is a TR1 C++ Library header. 
 */

#ifndef _GLIBCXX_TR1_TYPE_TRAITS
#define _GLIBCXX_TR1_TYPE_TRAITS 1

#pragma GCC system_header

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

namespace std _GLIBCXX_VISIBILITY(default)
{
namespace tr1
{
_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 [4.3].

  /// integral_constant
  template<typename _Tp, _Tp __v>
    struct integral_constant
    {
      static const _Tp                      value = __v;
      typedef _Tp                           value_type;
      typedef integral_constant<_Tp, __v>   type;
    };
  
  /// 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>
    const _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 [4.5.1].

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

  // composite type traits [4.5.2].
  
  /// 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_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				      || is_ame al_constant<bool, (is_arithmetic<_Tp>::value
				     