blob: e6fe23429fa205cd2dae4cc15ce92e3fcef6ab30 [file] [log] [blame]
// -*- C++ -*- Time-stamp: <08/07/20 19:10:15 ptr>
/*
* Copyright (c) 2007, 2008
* Petr Ovtchenkov
*
* Licensed under the Academic Free License version 3.0
*
* Derived from original <misc/type_traits.h> of 'complement' project
* [http://complement.sourceforge.net]
* to make it close to JTC1/SC22/WG21 C++ 0x working draft
* [http://www.open-std.org/Jtc1/sc22/wg21/docs/papers/2008/n2521.pdf]
*/
#ifndef __STLP_TYPE_TRAITS
#define __STLP_TYPE_TRAITS
#ifndef _STLP_OUTERMOST_HEADER_ID
# define _STLP_OUTERMOST_HEADER_ID 0x3
# include <stl/_prolog.h>
#endif
// libstdc++ v3, timestamp 20050519 (3.4.4) has __type_traits,
// libstdc++ v3, timestamp 20060306 (3.4.6) has __type_traits,
// while libstdc++ v3, 20050921 (4.0.2) not; use libstdc++ instead
// # if defined(STLPORT) || (defined(__GNUC__) && (__GNUC__ < 4)) /* !defined(__GLIBCXX__) || (defined(__GNUC__) && (__GNUC__ < 4)) */
_STLP_BEGIN_NAMESPACE
_STLP_BEGIN_TR1_NAMESPACE
namespace detail {
struct __select_types
{
typedef char __t1;
struct __t2
{
char __two[2];
};
};
template <class _Tp>
struct __instance :
public __select_types
{
private:
template <class _Up>
static __t1 __test(_Up(*)[1]);
template <class>
static __t2 __test(...);
public:
#ifdef _STLP_STATIC_CONST_INIT_BUG
static const bool __value;
#else
static const bool __value = sizeof(__test<_Tp>(0)) == sizeof(__select_types::__t1);
#endif
};
#ifdef _STLP_STATIC_CONST_INIT_BUG
template <class _Tp>
const bool __instance<_Tp>::__value = sizeof(__instance<_Tp>::__test<_Tp>(0)) == sizeof(__select_types::__t1);
#endif
template <class T>
struct __uoc_aux : // union or class
public __select_types
{
private:
template <class _Up>
static __t1 __test( int _Up::* );
template <class>
static __t2 __test(...);
public:
#ifdef __FIT_NO_INLINE_TEMPLATE_STATIC_INITIALISATION
static const bool __value;
#else
static const bool __value = sizeof(__test<T>(0)) == sizeof(__select_types::__t1);
#endif
};
#ifdef __FIT_NO_INLINE_TEMPLATE_STATIC_INITIALISATION
template <class T>
const bool __uoc_aux<T>::__value = sizeof(__uoc_aux<T>::__test<T>(0)) == sizeof(__select_types::__t1);
#endif
template <class T>
class __empty
{ };
template <class T, bool B>
class __inheritance_aux
{};
template <class T>
class __inheritance_aux<T,true> :
public T
{
public:
virtual ~__inheritance_aux()
{ }
};
#if 0
template <class T, bool B>
struct __virtual_aux
{
public:
#ifdef _STLP_STATIC_CONST_INIT_BUG
static const bool __value;
#else
static const bool __value = B ? (sizeof(__inheritance_aux<T,B>) == sizeof(T)) : false;
#endif
};
#ifdef _STLP_STATIC_CONST_INIT_BUG
template <class T, bool B>
const bool __virtual_aux<T,B>::__value = B ? (sizeof(__inheritance_aux<T,B>) == sizeof(T)) : false;
#endif
#endif
} // namespace detail
template <class _Tp, _Tp __v>
struct integral_constant
{
static const _Tp value = __v;
// enum { 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;
namespace detail {
template <typename _Tp>
struct __is_union_or_class :
public integral_constant<bool, __uoc_aux<_Tp>::__value>
{ };
#if 0
template<typename _Tp>
struct __is_vtbl : // has virtual table?
public integral_constant<bool, __virtual_aux<_Tp,__is_union_or_class<_Tp>::value >::__value>
{ };
#endif
template <typename _Tp>
struct __is_vtbl : // has virtual table?
public integral_constant<bool, __is_union_or_class<_Tp>::value ? (sizeof(__inheritance_aux<_Tp,__is_union_or_class<_Tp>::value>) == sizeof(_Tp)) : false >
{ };
} // namespace detail
#define __SPEC_(C,T,B) \
template <> \
struct C<T> : \
public integral_constant<bool, B> \
{ }
#define __CV_SPEC(C,T,B) \
__SPEC_(C,T,B); \
__SPEC_(C,const T,B); \
__SPEC_(C,volatile T,B); \
__SPEC_(C,const volatile T,B)
#define __SPEC_1(C,T,B) \
template <class _Tp> \
struct C<T> : \
public integral_constant<bool, B> \
{ }
#define __CV_SPEC_1(C,T,B) \
__SPEC_1(C,T,B); \
__SPEC_1(C,T const,B); \
__SPEC_1(C,T volatile,B); \
__SPEC_1(C,T const volatile,B)
#define __SPEC_2(C,T,B) \
template <class _Tp1, class _Tp2> \
struct C<T> : \
public integral_constant<bool, B> \
{ }
#define __CV_SPEC_2(C,T,B) \
__SPEC_2(C,T,B); \
__SPEC_2(C,T const,B); \
__SPEC_2(C,T volatile,B); \
__SPEC_2(C,T const volatile,B)
// [4.5.1] primary type categories:
template <class _Tp>
struct is_void :
public false_type
{ };
template <>
struct is_void<void> :
public true_type
{ };
template <class _Tp>
struct is_integral :
public false_type
{ };
__CV_SPEC(is_integral,bool,true);
__CV_SPEC(is_integral,char,true);
__CV_SPEC(is_integral,signed char,true);
__CV_SPEC(is_integral,unsigned char,true);
__CV_SPEC(is_integral,wchar_t,true);
__CV_SPEC(is_integral,short,true);
__CV_SPEC(is_integral,unsigned short,true);
__CV_SPEC(is_integral,int,true);
__CV_SPEC(is_integral,unsigned int,true);
__CV_SPEC(is_integral,long,true);
__CV_SPEC(is_integral,unsigned long,true);
__CV_SPEC(is_integral,long long,true);
__CV_SPEC(is_integral,unsigned long long,true);
template <class _Tp>
struct is_floating_point :
public false_type
{ };
__CV_SPEC(is_floating_point,float,true);
__CV_SPEC(is_floating_point,double,true);
__CV_SPEC(is_floating_point,long double,true);
template <class _Tp>
struct is_array :
public false_type
{ };
template <class _Tp, std::size_t _Sz>
struct is_array<_Tp[_Sz]> :
public true_type
{ };
template <class _Tp>
struct is_array<_Tp[]> :
public true_type
{ };
template <class _Tp>
struct is_pointer :
public false_type
{ };
__CV_SPEC_1(is_pointer,_Tp *,true);
template <class _Tp>
struct is_lvalue_reference :
public false_type
{ };
template <class _Tp>
struct is_lvalue_reference<_Tp&> :
public true_type
{ };
template <class _Tp>
struct is_rvalue_reference :
public false_type
{ };
// template <class _Tp>
// struct is_rvalue_reference<_Tp&&> :
// public true_type
// { };
template <class _Tp>
struct is_reference :
public false_type
{ };
template <class _Tp>
struct is_reference<_Tp&> :
public true_type
{ };
template <class _Tp>
struct is_function :
public integral_constant<bool, !(detail::__instance<_Tp>::__value
|| detail::__is_union_or_class<_Tp>::value
|| is_reference<_Tp>::value
|| is_void<_Tp>::value)>
{ };
template <class _Tp>
struct is_member_object_pointer :
public false_type
{ };
// _SPEC_FULL2(is_member_object_pointer, _Tp1 _Tp2::*,!is_function<_Tp1>::value);
template <class _Tp1, class _Tp2>
struct is_member_object_pointer<_Tp1 _Tp2::*> :
public integral_constant<bool, !is_function<_Tp1>::value>
{ };
template <class _Tp1, class _Tp2>
struct is_member_object_pointer<_Tp1 _Tp2::* const> :
public integral_constant<bool, !is_function<_Tp1>::value>
{ };
template <class _Tp1, class _Tp2>
struct is_member_object_pointer<_Tp1 _Tp2::* volatile> :
public integral_constant<bool, !is_function<_Tp1>::value>
{ };
template <class _Tp1, class _Tp2>
struct is_member_object_pointer<_Tp1 _Tp2::* const volatile> :
public integral_constant<bool, !is_function<_Tp1>::value>
{ };
template <class _Tp>
struct is_member_function_pointer :
public false_type
{ };
// _SPEC_FULL2(is_member_function_pointer,_Tp1 _Tp2::*,is_function<_Tp1>::value);
template <class _Tp1, class _Tp2>
struct is_member_function_pointer<_Tp1 _Tp2::*> :
public integral_constant<bool, is_function<_Tp1>::value>
{ };
template <class _Tp1, class _Tp2>
struct is_member_function_pointer<_Tp1 _Tp2::* const> :
public integral_constant<bool, is_function<_Tp1>::value>
{ };
template <class _Tp1, class _Tp2>
struct is_member_function_pointer<_Tp1 _Tp2::* volatile> :
public integral_constant<bool, is_function<_Tp1>::value>
{ };
template <class _Tp1, class _Tp2>
struct is_member_function_pointer<_Tp1 _Tp2::* const volatile> :
public integral_constant<bool, is_function<_Tp1>::value>
{ };
template <class _Tp>
struct is_member_pointer :
public integral_constant<bool, (is_member_object_pointer<_Tp>::value || is_member_function_pointer<_Tp>::value)>
{ };
// 4.5.2 composite type categories
template <class _Tp>
struct is_arithmetic :
public integral_constant<bool, (is_integral<_Tp>::value || is_floating_point<_Tp>::value)>
{ };
template <class _Tp>
struct is_fundamental :
public integral_constant<bool, (is_arithmetic<_Tp>::value || is_void<_Tp>::value)>
{ };
// [4.5.1] primary type categories (continued):
template <class _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
|| detail::__is_union_or_class<_Tp>::value) >
{ };
template <class T>
struct is_union
{ };
template <class T>
struct is_class
{ };
// is_function (above)
// 4.5.2 composite type categories (continued)
// is_arithmetic (above)
// is_fundamental (above)
template <class _Tp>
struct is_object :
public integral_constant<bool, (is_arithmetic<_Tp>::value ||
is_array<_Tp>::value ||
is_pointer<_Tp>::value ||
is_member_pointer<_Tp>::value ||
detail::__is_union_or_class<_Tp>::value)>
{ };
template <class _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 <class _Tp>
struct is_compound :
public integral_constant<bool, !is_fundamental<_Tp>::value>
{ };
// is_member_pointer
// 4.5.3 type properties:
template <class _Tp>
struct is_const :
public false_type
{ };
template <class _Tp>
struct is_const<_Tp const> :
public true_type
{ };
template <class _Tp>
struct is_volatile :
public false_type
{ };
template <class _Tp>
struct is_volatile<_Tp volatile> :
public true_type
{ };
// 4.7.3 array modifications:
template <class _Tp>
struct remove_extent
{
typedef _Tp type;
};
template <class _Tp, std::size_t _Sz>
struct remove_extent<_Tp[_Sz]>
{
typedef _Tp type;
};
template <class _Tp>
struct remove_extent<_Tp[]>
{
typedef _Tp type;
};
template <class _Tp>
struct remove_all_extents
{
typedef _Tp type;
};
template <class _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;
};
// 4.5.3 type properties (continued):
template <class _Tp>
struct is_trivial :
public integral_constant<bool, (is_void<_Tp>::value
|| is_scalar<typename remove_all_extents<_Tp>::type>::value)>
{ };
template <class _Tp>
struct is_standard_layout :
public integral_constant<bool, (is_void<_Tp>::value
|| is_scalar<typename remove_all_extents<_Tp>::type>::value)>
{ };
template <class _Tp>
struct is_pod :
public integral_constant<bool, (is_void<_Tp>::value
|| is_scalar<typename remove_all_extents<_Tp>::type>::value)>
{ };
template<typename _Tp>
struct is_empty
: public integral_constant<bool, (detail::__is_union_or_class<_Tp>::value
&& (sizeof(detail::__empty<_Tp>) == sizeof(_Tp)))>
{ };
// is_polimorphic
// is_abstract
template <class _Tp>
struct has_trivial_constructor :
public integral_constant<bool, is_pod<_Tp>::value>
{ };
template <class _Tp>
struct has_trivial_copy :
public integral_constant<bool, is_pod<_Tp>::value>
{ };
template <class _Tp>
struct has_trivial_assign :
public integral_constant<bool, is_pod<_Tp>::value>
{ };
template <class _Tp>
struct has_trivial_destructor :
public integral_constant<bool, is_pod<_Tp>::value>
{ };
template <class _Tp>
struct has_nothrow_constructor :
public integral_constant<bool, is_pod<_Tp>::value>
{ };
template <class _Tp>
struct has_nothrow_copy :
public integral_constant<bool, is_pod<_Tp>::value>
{ };
template <class _Tp>
struct has_nothrow_assign :
public integral_constant<bool, is_pod<_Tp>::value>
{ };
template <class _Tp>
struct has_virtual_destructor :
public false_type
{ };
template <class _Tp>
struct is_signed :
public false_type
{ };
__CV_SPEC(is_signed,signed char,true);
__CV_SPEC(is_signed,short,true);
__CV_SPEC(is_signed,int,true);
__CV_SPEC(is_signed,long,true);
__CV_SPEC(is_signed,long long,true);
template <class _Tp>
struct is_unsigned :
public false_type
{ };
__CV_SPEC(is_unsigned,unsigned char,true);
__CV_SPEC(is_unsigned,unsigned short,true);
__CV_SPEC(is_unsigned,unsigned int,true);
__CV_SPEC(is_unsigned,unsigned long,true);
__CV_SPEC(is_unsigned,unsigned long long,true);
// alignment_of
// rank
// extent
// 4.6 type relations:
template <class _Tp1, class _Tp2>
struct is_same :
public false_type
{ };
template <class _Tp>
struct is_same<_Tp, _Tp> :
public true_type
{ };
// is_base_of
// is_convertible
// 4.7.1 const-volatile modifications
template <class _Tp>
struct remove_const
{
typedef _Tp type;
};
template <class _Tp>
struct remove_const<_Tp const>
{
typedef _Tp type;
};
template <class _Tp>
struct remove_volatile
{
typedef _Tp type;
};
template <class _Tp>
struct remove_volatile<_Tp volatile>
{
typedef _Tp type;
};
template <class _Tp>
struct remove_cv
{
typedef typename remove_const<typename remove_volatile<_Tp>::type>::type type;
};
template <class _Tp>
struct add_const
{
typedef _Tp const type;
};
template <class _Tp>
struct add_volatile
{
typedef _Tp volatile type;
};
template <class _Tp>
struct add_cv
{
typedef typename add_const<typename add_volatile<_Tp>::type>::type type;
};
// 4.7.2 reference modifications:
template <class _Tp>
struct remove_reference
{
typedef _Tp type;
};
template <class _Tp>
struct remove_reference<_Tp&>
{
typedef _Tp type;
};
template <class _Tp>
struct add_reference
{
typedef _Tp& type;
};
template <class _Tp>
struct add_reference<_Tp&>
{
typedef _Tp& type;
};
// 4.7.3 array modifications (see above)
// 4.7.4 pointer modifications:
template <class _Tp>
struct remove_pointer
{
typedef _Tp type;
};
template <class _Tp>
struct remove_pointer<_Tp *>
{
typedef _Tp type;
};
template <class _Tp>
struct remove_pointer<_Tp * const>
{
typedef _Tp type;
};
template <class _Tp>
struct remove_pointer<_Tp * volatile>
{
typedef _Tp type;
};
template <class _Tp>
struct remove_pointer<_Tp * const volatile>
{
typedef _Tp type;
};
template <class _Tp>
struct add_pointer
{
typedef typename remove_reference<_Tp>::type * type;
};
// 20.5.7 other transformations:
// template <std::size_t Len, std::size_t Align> struct aligned_storage;
// template <std::size_t Len, class... Types> struct aligned_union;
namespace detail {
template <bool,class _U>
struct _decay_aux2
{
typedef typename remove_cv<_U>::type type;
};
template <class _U>
struct _decay_aux2<true,_U>
{
typedef typename add_pointer<_U>::type type;
};
template <bool, class _U>
struct _decay_aux1
{
typedef typename _decay_aux2<is_function<_U>::value,_U>::type type;
};
template <class _U>
struct _decay_aux1<true,_U>
{
typedef typename remove_extent<_U>::type* type;
};
} // namespace detail
template <class _Tp>
class decay
{
private:
typedef typename remove_reference<_Tp>::type _U;
public:
typedef typename detail::_decay_aux1<is_array<_U>::value,_U>::type type;
};
template <bool, class _Tp = void>
struct enable_if
{
};
template <class _Tp>
struct enable_if<true,_Tp>
{
typedef _Tp type;
};
template <bool, class _Tp1, class _Tp2>
struct conditional
{
typedef _Tp2 type;
};
template <class _Tp1, class _Tp2>
struct conditional<true,_Tp1,_Tp2>
{
typedef _Tp1 type;
};
// template <class... _Tp> struct common_type;
#undef __CV_SPEC
#undef __SPEC_
#undef __CV_SPEC_1
#undef __SPEC_1
#undef __CV_SPEC_2
#undef __SPEC_2
_STLP_END_NAMESPACE // tr1
_STLP_END_NAMESPACE
// # else // __GLIBCXX__ && (__GNUC__ >= 4) && !STLPORT
// # include <tr1/type_traits>
// # endif
#if (_STLP_OUTERMOST_HEADER_ID == 0x3)
# include <stl/_epilog.h>
# undef _STLP_OUTERMOST_HEADER_ID
#endif
#endif // __STLP_TYPE_TRAITS