Forked from
Core Modules / dune-common
4758 commits behind the upstream repository.
-
Oliver Sander authored
Because C++11 implements this differently, and we now have an stl-compliant implementation to switch to. I would deprecate isPointer and isReference too, but I can't find a way to do it.
Oliver Sander authoredBecause C++11 implements this differently, and we now have an stl-compliant implementation to switch to. I would deprecate isPointer and isReference too, but I can't find a way to do it.
typetraits.hh 12.53 KiB
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
#ifndef DUNE_TYPETRAITS_HH
#define DUNE_TYPETRAITS_HH
#if defined HAVE_TYPE_TRAITS
#include <type_traits>
#elif defined HAVE_TR1_TYPE_TRAITS
#include <tr1/type_traits>
#endif
#include <dune/common/deprecated.hh>
namespace Dune
{
/**
* @file
* @brief Traits for type conversions and type information.
* @author Markus Blatt, Christian Engwer
*/
/** @addtogroup Common
*
* @{
*/
/**
* @brief Just an empty class
*/
struct Empty {};
/**
* @brief General type traits class to check whether type is reference or
* pointer type
*
* \deprecated This class will be replaced by alternatives found in the C++11 stl.
* - Use is_pointer<T>::value instead of TypeTraits<T>::isPointer
* - Use is_lvalue_reference<T>::value instead of TypeTraits<T>::isReference
* - Use remove_pointer<T>::type instead of TypeTraits<T>::PointeeType
* - Use remove_reference<T>::type instead of TypeTraits<T>::ReferredType
*/
template <typename T>
class TypeTraits
{
private:
template <class U>
struct PointerTraits {
enum { result = false };
typedef Empty PointeeType;
};
template <class U>
struct PointerTraits<U*> {
enum { result = true };
typedef U PointeeType;
};
template <class U> struct ReferenceTraits
{
enum { result = false };
typedef U ReferredType;
};
template <class U> struct ReferenceTraits<U&>
{
enum { result = true };
typedef U ReferredType;
};
public:
enum { isPointer = PointerTraits<T>::result };
typedef typename PointerTraits<T>::PointeeType PointeeType DUNE_DEPRECATED_MSG("Use remove_pointer instead!");
enum { isReference = ReferenceTraits<T>::result };
typedef typename ReferenceTraits<T>::ReferredType ReferredType DUNE_DEPRECATED_MSG("Use remove_reference instead!");
};
/**
* @brief Determines wether a type is const or volatile and provides the
* unqualified types.
*/
template<typename T>
struct ConstantVolatileTraits
{
enum {
/** @brief True if T has a volatile specifier. */
isVolatile=false,
/** @brief True if T has a const qualifier. */
isConst=false
};
/** @brief The unqualified type. */
typedef T UnqualifiedType;
/** @brief The const type. */
typedef const T ConstType;
/** @brief The const volatile type. */
typedef const volatile T ConstVolatileType;
};
template<typename T>
struct ConstantVolatileTraits<const T>
{
enum {
isVolatile=false, isConst=true
};
typedef T UnqualifiedType;
typedef const UnqualifiedType ConstType;
typedef const volatile UnqualifiedType ConstVolatileType;
};
template<typename T>
struct ConstantVolatileTraits<volatile T>
{
enum {
isVolatile=true, isConst=false
};
typedef T UnqualifiedType;
typedef const UnqualifiedType ConstType;
typedef const volatile UnqualifiedType ConstVolatileType;
};
template<typename T>
struct ConstantVolatileTraits<const volatile T>
{
enum {
isVolatile=true, isConst=true
};
typedef T UnqualifiedType;
typedef const UnqualifiedType ConstType;
typedef const volatile UnqualifiedType ConstVolatileType;
};
/** @brief Tests wether a type is volatile. */
template<typename T>
struct IsVolatile
{
enum {
/** @brief True if The type is volatile. */
value=ConstantVolatileTraits<T>::isVolatile
};
};
/** @brief Tests wether a type is constant. */
template<typename T>
struct IsConst
{
enum {
/** @brief True if The type is constant. */
value=ConstantVolatileTraits<T>::isConst
};
};
template<typename T, bool isVolatile>
struct RemoveConstHelper
{
typedef typename ConstantVolatileTraits<T>::UnqualifiedType Type;
};
template<typename T>
struct RemoveConstHelper<T,true>
{
typedef volatile typename ConstantVolatileTraits<T>::UnqualifiedType Type;
};
#if defined HAVE_TYPE_TRAITS
using std::remove_const;
#elif defined HAVE_TR1_TYPE_TRAITS
using std::tr1::remove_const;
#else
/**
* @brief Removes a const qualifier while preserving others.
*/
template<typename T>
struct remove_const
{
typedef typename RemoveConstHelper<T, IsVolatile<T>::value>::Type type;
};
#endif
#if defined HAVE_TYPE_TRAITS
using std::remove_reference;
#elif defined HAVE_TR1_TYPE_TRAITS
using std::tr1::remove_reference;
#else
//! Remove a reference from a type
/**
* If the template parameter \c T matches \c T1&, then the member typedef \c
* type is \c T1, otherwise it is \c T.
*/
template<typename T> struct remove_reference {
//! T with references removed
typedef T type;
};
# ifndef DOXYGEN
template<typename T> struct remove_reference<T&> {
typedef T type;
};
# endif // ! defined(DOXYGEN)
#endif
/**
* @brief Checks wether a type is convertible to another.
*
* @tparam From type you want to convert
* @tparam To type you want to obtain
*
* Inspired by
* <A HREF="http://www.kotiposti.net/epulkkin/instructive/base-class-determination.html"> this website</A>
*/
template<class From, class To>
class Conversion
{
typedef char Small;
struct Big {char dummy[2];};
static Small test(To);
static Big test(...);
static typename TypeTraits< From >::ReferredType &makeFrom ();
public:
enum {
/** @brief True if the conversion exists. */
exists = sizeof(test(makeFrom())) == sizeof(Small),
/** @brief Whether the conversion exists in both ways. */
isTwoWay = exists && Conversion<To,From>::exists,
/** @brief True if To and From are the same type. */
sameType = false
};
Conversion(){}
};
template <class From>
class Conversion<From, void>
{
public:
enum {
exists = false,
isTwoWay = false,
sameType = false
};
};
template <class To>
class Conversion<void, To>
{
public:
enum {
exists = false,
isTwoWay = false,
sameType = false
};
};
template<>
class Conversion< int, double >
{
public:
enum {
exists = true,
isTwoWay = false,
sameType = false
};
};
template<class T>
class Conversion<T,T>{
public:
enum { exists=true, isTwoWay=true, sameType=true};
};
/**
* @brief Checks wether a type is derived from another.
*
* @tparam Base the potential base class you want to test for
* @tparam Derived type you want to test
*
* Similar idea to
* <A HREF="http://www.kotiposti.net/epulkkin/instructive/base-class-determination.html"> this website</A>
*/
template <class Base, class Derived>
class IsBaseOf
{
typedef typename ConstantVolatileTraits< typename TypeTraits< Base >::ReferredType >::UnqualifiedType RawBase;
typedef typename ConstantVolatileTraits< typename TypeTraits< Derived >::ReferredType >::UnqualifiedType RawDerived;
typedef char Small;
struct Big {char dummy[2];};
static Small test(RawBase*);
static Big test(...);
static RawDerived* &makePtr ();
public:
enum {
/** @brief True if Base is a base class of Derived. */
value = sizeof(test(makePtr())) == sizeof(Small)
};
IsBaseOf(){}
};
/**
* @brief Checks wether two types are interoperable.
*
* Two types are interoperable if conversions in either directions
* exists.
*/
template<class T1, class T2>
struct IsInteroperable
{
enum {
/**
* @brief True if either a conversion from T1 to T2 or vice versa
* exists.
*/
value = Conversion<T1,T2>::exists || Conversion<T2,T1>::exists
};
};
#ifdef HAVE_TYPE_TRAITS
using std::enable_if;
#else
/**
* @brief Enable typedef if condition is met.
*
* Replacement implementation for compilers without this in the stl.
* Depending on the value of b the type T is provided as typedef type.
*/
template<bool b, typename T=void>
struct enable_if
{
typedef T type;
};
template<typename T>
struct enable_if<false,T>
{};
#endif
/**
* @brief Enable typedef if two types are interoperable.
*
* (also see IsInteroperable)
*/
template<class T1, class T2, class Type>
struct EnableIfInterOperable
: public enable_if<IsInteroperable<T1,T2>::value, Type>
{};
#if defined HAVE_TYPE_TRAITS
using std::is_same;
#elif defined HAVE_TR1_TYPE_TRAITS
using std::tr1::is_same;
#else
/**
* @brief Compile time test for testing whether
* two types are the same.
*/
template<typename T1, typename T2>
struct is_same
{
//! Whether T1 is the same type as T2.
enum {
/* @brief Whether T1 is the same type as T2. */
value=false
};
};
template<typename T>
struct is_same<T,T>
{
enum { value=true};
};
#endif
/**
* @brief Select a type based on a condition.
*
* If template parameter first is true T1 is selected
* otherwise T2 will be selected.
* The selected type is accessible through the typedef
* Type.
*
* \deprecated Will be removed after dune-common-2.3, use 'conditional' instead.
*/
template<bool first, class T1, class T2>
struct SelectType
{
/**
* @brief The selected type.
*
* if first is true this will be type T1 and
* otherwise T2
*/
typedef T1 Type DUNE_DEPRECATED_MSG("Use Dune::conditional::type instead");
} DUNE_DEPRECATED;
template<class T1, class T2>
struct SelectType<false,T1,T2>
{
typedef T2 Type DUNE_DEPRECATED_MSG("Use Dune::conditional::type instead");
};
#if DOXYGEN || !HAVE_STD_CONDITIONAL
/**
* @brief Select a type based on a condition.
*
* If template parameter first is true T1 is selected
* otherwise T2 will be selected.
* The selected type is accessible through the typedef
* type.
*
* \note If available, this uses C++11 std::conditional, otherwise it provides
* a reimplementation.
*/
template<bool first, class T1, class T2>
struct conditional
{
/**
* @brief The selected type
*
* if first is true this will be type T1 and
* T2 otherwise
*/
typedef T1 type;
};
template<class T1, class T2>
struct conditional<false,T1,T2>
{
typedef T2 type;
};
#else // DOXYGEN || !HAVE_STD_CONDITIONAL
// pull in default implementation
using std::conditional;
#endif // DOXYGEN || !HAVE_STD_CONDITIONAL
////////////////////////////////////////////////////////////////////////
//
// integral_constant (C++0x 20.7.3 "Helper classes")
//
#if HAVE_INTEGRAL_CONSTANT
using std::integral_constant;
using std::true_type;
using std::false_type;
#else // #if HAVE_INTEGRAL_CONSTANT
//! Generate a type for a given integral constant
/**
* \tparam T Type of the constant.
* \tparam v Value of the constant.
*/
template <class T, T v>
struct integral_constant {
//! value this type was generated for
static const T value = v;
//! type of value
typedef T value_type;
//! type of this class itself
typedef integral_constant<T,v> type;
//! conversion to value_type/T
operator value_type() { return value; }
};
//! type for true
typedef integral_constant<bool, true> true_type;
//! type for false
typedef integral_constant<bool, false> false_type;
#endif // #else // #if HAVE_INTEGRAL_CONSTANT
template<typename>
struct __is_pointer_helper
: public false_type { };
template<typename T>
struct __is_pointer_helper<T*>
: public true_type { };
/// is_pointer
template<typename T>
struct is_pointer
: public integral_constant<bool, (__is_pointer_helper<T>::value)>
{ };
// Helper class for is_lvalue_reference
template<typename>
struct __is_lvalue_reference_helper
: public false_type { };
template<typename T>
struct __is_lvalue_reference_helper<T&>
: public true_type { };
/** \brief Determine whether a type is a lvalue reference type */
template<typename T>
struct is_lvalue_reference
: public integral_constant<bool, (__is_lvalue_reference_helper<T>::value)>
{ };
template<typename _Tp>
struct __remove_pointer_helper
{ typedef _Tp type; };
template<typename _Tp>
struct __remove_pointer_helper<_Tp*>
{ typedef _Tp type; };
/** \brief Return the type a pointer type points to
*
* \note When the argument T is not a pointer, TypeTraits::PointeeType returns Dune::Empty,
* while Dune::remove_pointer (as std::remove_pointer), returns T itself.
*/
template<typename _Tp>
struct remove_pointer
: public __remove_pointer_helper<typename remove_const<_Tp>::type >
{ };
/** @} */
}
#endif