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

// Copyright (C) 2004 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.

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

#ifndef _TYPE_TRAITS
#define _TYPE_TRAITS 1

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

//namespace std::tr1
namespace std
{
namespace tr1
{
  /// @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;
  
#define _DEFINE_PRIMARY_SPEC_HELPER(_Primary, _Type)           \
  template<>                                                   \
    struct _Primary<_Type>                                     \
    : public true_type { };                            

#define _DEFINE_PRIMARY_SPEC(_Primary, _Type)                  \
  _DEFINE_PRIMARY_SPEC_HELPER(_Primary, _Type)                 \
  _DEFINE_PRIMARY_SPEC_HELPER(_Primary, _Type const)           \
  _DEFINE_PRIMARY_SPEC_HELPER(_Primary, _Type volatile)        \
  _DEFINE_PRIMARY_SPEC_HELPER(_Primary, _Type const volatile)
  
  /// @brief  primary type categories [4.5.1].
  template<typename>
    struct is_void
    : public false_type { };
  _DEFINE_PRIMARY_SPEC(is_void, void)

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

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

  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 _Tp>
    struct is_pointer;
  
  template<typename>
    struct is_reference
    : public false_type { };

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

  template<typename _Tp>
    struct is_enum;
  
  template<typename _Tp>
    struct is_union;
  
  template<typename _Tp>
    struct is_class;
  
  template<typename _Tp>
    struct is_function;

#undef _DEFINE_PRIMARY_SPEC_HELPER
#undef _DEFINE_PRIMARY_SPEC

  /// @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_arithmetic<_Tp>::value
				      || is_void<_Tp>::value)>
    { };

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

  template<typename _Tp>
    struct is_member_pointer
    : public integral_constant<bool,
			       (is_member_object_pointer<_Tp>::value
				|| is_member_function_pointer<_Tp>::value)>
    { };
  
  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)>
    { };
  
  template<typename _Tp>
    struct is_compound
    : public integral_constant<bool, !is_fundamental<_Tp>::value> { };
   
  /// @brief  type properties [4.5.3].
  template<typename>
    struct is_const
    : public false_type { };

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

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

  template<typename _Tp>
    struct is_pod;
  
  template<typename _Tp>
    struct is_empty;
  
  template<typename _Tp>
    struct is_polymorphic;
  
  template<typename _Tp>
    struct is_abstract;
  
  template<typename _Tp>
    struct has_trivial_constructor;
  
  template<typename _Tp>
    struct has_trivial_copy;

  template<typename _Tp>
    struct has_trivial_assign;
  
  template<typename _Tp>
    struct has_trivial_destructor;
  
  template<typename _Tp>
    struct has_nothrow_constructor;
  
  template<typename _Tp>
    struct has_nothrow_copy;

  template<typename _Tp>
    struct has_nothrow_assign;
  
  template<typename _Tp>
    struct has_virtual_destructor
    : public false_type { };
  
  template<typename _Tp>
    struct is_signed;
  
  template<typename _Tp>
    struct is_unsigned;
   
  template<typename _Tp>
    struct alignment_of;
  
  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> { };
   
  template<typename _Tp, unsigned _Uint = 0>
    struct extent;
  
  /// @brief  relationships between types [4.6].
  template<typename, typename>
    struct is_same
    : public false_type { };

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

  template<typename _From, typename _To>
    struct is_convertible;
  
  template<typename _Base, typename _Derived>
    struct is_base_of;

  /// @brief  const-volatile modifications [4.7.1].
  template<typename _Tp>
    struct remove_const
    {
      typedef _Tp     type;
    };

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

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

  /// @brief  reference modifications [4.7.2].
  template<typename _Tp>
    struct remove_reference
    {
      typedef _Tp     type;
    };

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

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

  /// @brief  array modififications [4.7.3].
  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;
    };

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

  /// @brief  pointer modifications [4.7.4].
  template<typename _Tp>
    struct remove_pointer;
  
  template<typename _Tp>
    struct add_pointer;

  /// @brief  other transformations [4.8].
  template<std::size_t _Len, std::size_t _Align>
    struct aligned_storage;
}
}

#endif
