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

// Copyright (C) 2004, 2005, 2006 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 2, 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.

// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING.  If not, write to the Free
// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
// USA.

// As a special exception, you may use this file as part of a free software
// library without restriction.  Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License.  This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.

/** @file tr1/type_traits
 *  This is a TR1 C++ Library header. 
 */

#ifndef _TR1_TYPE_TRAITS
#define _TR1_TYPE_TRAITS 1

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

// namespace std::tr1
namespace std
{
_GLIBCXX_BEGIN_NAMESPACE(tr1)

  // For use in __in_array and elsewhere.
  struct __sfinae_types
  {
    typedef char __one;
    typedef struct { char __arr[2]; } __two;
  };

  template<typename _Tp>
    struct __in_array
    : public __sfinae_types
    {
    private:
      template<typename _Up>
        static __one __test(_Up(*)[1]);
      template<typename>
        static __two __test(...);
    
    public:
      static const bool __value = sizeof(__test<_Tp>(0)) == 1;
    };

#define _DEFINE_SPEC_BODY(_Value)                                    \
    : public integral_constant<bool, _Value> { };

#define _DEFINE_SPEC_0_HELPER(_Spec, _Value)                         \
  template<>                                                         \
    struct _Spec                                                     \
    _DEFINE_SPEC_BODY(_Value)

#define _DEFINE_SPEC_1_HELPER(_Spec, _Value)                         \
  template<typename _Tp>                                             \
    struct _Spec                                                     \
    _DEFINE_SPEC_BODY(_Value)
      
#define _DEFINE_SPEC_2_HELPER(_Spec, _Value)                         \
  template<typename _Tp, typename _Cp>                               \
    struct _Spec                                                     \
    _DEFINE_SPEC_BODY(_Value)

#define _DEFINE_SPEC(_Order, _Trait, _Type, _Value)                  \
  _DEFINE_SPEC_##_Order##_HELPER(_Trait<_Type>, _Value)              \
  _DEFINE_SPEC_##_Order##_HELPER(_Trait<_Type const>, _Value)        \
  _DEFINE_SPEC_##_Order##_HELPER(_Trait<_Type volatile>, _Value)     \
  _DEFINE_SPEC_##_Order##_HELPER(_Trait<_Type const volatile>, _Value)

  /// @brief  helper classes [4.3].
  template<typename _Tp, _Tp __v>
    struct integral_constant
    {
      static const _Tp                      value = __v;
      typedef _Tp                           value_type;
      typedef integral_constant<_Tp, __v>   type;
    };
  typedef integral_constant<bool, true>     true_type;
  typedef integral_constant<bool, false>    false_type;

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

  /// @brief  primary type categories [4.5.1].
  template<typename>
    struct is_void
    : public false_type { };
  _DEFINE_SPEC(0, is_void, void, true)

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

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

  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
    : public false_type { };
  _DEFINE_SPEC(1, is_pointer, _Tp*, true)
 
  template<typename>
    struct is_reference
    : public false_type { };

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

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

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

  template<typename _Tp>
    struct is_enum
    : public integral_constant<bool, !(is_fundamental<_Tp>::value
				       || is_array<_Tp>::value
				       || is_pointer<_Tp>::value
				       || is_reference<_Tp>::value
				       || is_member_pointer<_Tp>::value
				       || is_function<_Tp>::value
				       || __is_union_or_class<_Tp>::value)>
    { };

  template<typename>
    struct is_union { };

  template<typename>
    struct is_class { };

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

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

  template<typename _Tp>
    struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_  struct is_fundamental
    : public integral_constant<bool, (is_ 