blob: ce9ee1b06f8d84d4a2c83c07fc98ba7d1b6b48a8 [file] [log] [blame]
// C++0x type_traits -*- C++ -*-
// Copyright (C) 2007, 2008, 2009 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 <c++0x_warning.h>
#else
#if defined(_GLIBCXX_INCLUDE_AS_TR1)
# error C++0x header cannot be included from TR1 header
#endif
#include <cstddef>
#if defined(_GLIBCXX_INCLUDE_AS_CXX0X)
# include <tr1_impl/type_traits>
#else
# define _GLIBCXX_INCLUDE_AS_CXX0X
# define _GLIBCXX_BEGIN_NAMESPACE_TR1
# define _GLIBCXX_END_NAMESPACE_TR1
# define _GLIBCXX_TR1
# include <tr1_impl/type_traits>
# undef _GLIBCXX_TR1
# undef _GLIBCXX_END_NAMESPACE_TR1
# undef _GLIBCXX_BEGIN_NAMESPACE_TR1
# undef _GLIBCXX_INCLUDE_AS_CXX0X
#endif
namespace std
{
/** @addtogroup metaprogramming
* @{
*/
// 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, _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_pod
template<typename _Tp>
struct is_pod
: public integral_constant<bool, __is_pod(_Tp)>
{ };
/// 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_assign
template<typename _Tp>
struct has_trivial_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_assign
template<typename _Tp>
struct has_nothrow_assign
: public integral_constant<bool, __has_nothrow_assign(_Tp)>
{ };
/// is_base_of
template<typename _Base, typename _Derived>
struct is_base_of
: public integral_constant<bool, __is_base_of(_Base, _Derived)>
{ };
// Relationships between types.
template<typename _From, typename _To>
struct __is_convertible_simple
: public __sfinae_types
{
private:
static __one __test(_To);
static __two __test(...);
static _From __makeFrom();
public:
static const bool __value = sizeof(__test(__makeFrom())) == 1;
};
template<typename _Tp>
struct __is_int_or_cref
{
typedef typename remove_reference<_Tp>::type __rr_Tp;
static const bool __value = (is_integral<_Tp>::value
|| (is_integral<__rr_Tp>::value
&& is_const<__rr_Tp>::value
&& !is_volatile<__rr_Tp>::value));
};
template<typename _From, typename _To,
bool = (is_void<_From>::value || is_void<_To>::value
|| is_function<_To>::value || is_array<_To>::value
// This special case is here only to avoid warnings.
|| (is_floating_point<typename
remove_reference<_From>::type>::value
&& __is_int_or_cref<_To>::__value))>
struct __is_convertible_helper
{
// "An imaginary lvalue of type From...".
static const bool __value = (__is_convertible_simple<typename
add_lvalue_reference<_From>::type,
_To>::__value);
};
template<typename _From, typename _To>
struct __is_convertible_helper<_From, _To, true>
{ static const bool __value = (is_void<_To>::value
|| (__is_int_or_cref<_To>::__value
&& !is_void<_From>::value)); };
// XXX FIXME
// The C++0x specifications are different, see N2255.
/// is_convertible
template<typename _From, typename _To>
struct is_convertible
: public integral_constant<bool,
__is_convertible_helper<_From, _To>::__value>
{ };
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>
struct decay
{
private:
typedef typename remove_reference<_Tp>::type __remove_type;
public:
typedef typename __decay_selector<__remove_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>
struct __match_cv_qualifiers
{
private:
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>
struct __make_unsigned_selector;
template<typename _Tp>
struct __make_unsigned_selector<_Tp, true, false>
{
private:
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>
struct __make_unsigned_selector<_Tp, false, true>
{
private:
// 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>
struct __make_signed_selector;
template<typename _Tp>
struct __make_signed_selector<_Tp, true, false>
{
private:
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>
struct __make_signed_selector<_Tp, false, true>
{
private:
// 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>
{
static_assert(sizeof(_Tp) > 0, "must be complete type");
typedef _Tp type;
};
template<typename _Tp, typename _Up>
class common_type<_Tp, _Up>
{
static_assert(sizeof(_Tp) > 0, "must be complete type");
static_assert(sizeof(_Up) > 0, "must be complete type");
static _Tp&& __t();
static _Up&& __u();
// HACK: Prevents optimization of ?: in the decltype
// expression when the condition is the literal, "true".
// See, PR36628.
static bool __true_or_false();
public:
typedef decltype(__true_or_false() ? __t() : __u()) 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;
};
// @} group metaprogramming
}
#endif // __GXX_EXPERIMENTAL_CXX0X__
#endif // _GLIBCXX_TYPE_TRAITS