blob: 8648d48bec9d9c351b0ad5e663fad31fa33b9b54 [file] [log] [blame]
// common_type.hpp ---------------------------------------------------------//
// Copyright 2008 Howard Hinnant
// Copyright 2008 Beman Dawes
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_EX_TYPE_TRAITS_EXT_COMMON_TYPE_HPP
#define BOOST_EX_TYPE_TRAITS_EXT_COMMON_TYPE_HPP
#include <boost/config.hpp>
//----------------------------------------------------------------------------//
#if defined(BOOST_NO_VARIADIC_TEMPLATES)
#define BOOST_EX_COMMON_TYPE_ARITY 3
#endif
//----------------------------------------------------------------------------//
#if defined(BOOST_NO_DECLTYPE) && !defined(BOOST_EX_COMMON_TYPE_DONT_USE_TYPEOF)
#define BOOST_TYPEOF_SILENT
#include <boost/typeof/typeof.hpp> // boost wonders never cease!
#endif
//----------------------------------------------------------------------------//
#ifndef BOOST_NO_STATIC_ASSERT
#define BOOST_EX_COMMON_TYPE_STATIC_ASSERT(CND, MSG, TYPES) static_assert(CND,MSG)
#elif defined(BOOST_EX_COMMON_TYPE_USES_STATIC_ASSERT)
#include <boost/static_assert.hpp>
#define BOOST_EX_COMMON_TYPE_STATIC_ASSERT(CND, MSG, TYPES) BOOST_STATIC_ASSERT(CND)
#elif defined(BOOST_EX_COMMON_TYPE_USES_MPL_ASSERT)
#include <boost/mpl/assert.hpp>
#include <boost/mpl/bool.hpp>
#define BOOST_EX_COMMON_TYPE_STATIC_ASSERT(CND, MSG, TYPES) \
BOOST_MPL_ASSERT_MSG(boost::mpl::bool_< (CND) >::type::value, MSG, TYPES)
#else
//~ #elif defined(BOOST_EX_COMMON_TYPE_USES_ARRAY_ASSERT)
#define BOOST_EX_COMMON_TYPE_CONCAT(A,B) A##B
#define BOOST_EX_COMMON_TYPE_NAME(A,B) BOOST_EX_COMMON_TYPE_CONCAT(A,B)
#define BOOST_EX_COMMON_TYPE_STATIC_ASSERT(CND, MSG, TYPES) static char BOOST_EX_COMMON_TYPE_NAME(__boost_common_type_test_,__LINE__)[(CND)?1:-1]
//~ #define BOOST_EX_COMMON_TYPE_STATIC_ASSERT(CND, MSG, TYPES)
#endif
#if !defined(BOOST_NO_STATIC_ASSERT) || !defined(BOOST_EX_COMMON_TYPE_USES_MPL_ASSERT)
#define BOOST_EX_COMMON_TYPE_MUST_BE_A_COMPLE_TYPE "must be complete type"
#endif
#if defined(BOOST_NO_DECLTYPE) && defined(BOOST_EX_COMMON_TYPE_DONT_USE_TYPEOF)
#include "detail/common_type.hpp"
#include <boost/type_traits/remove_cv.hpp>
#endif
#include <boost/mpl/if.hpp>
#include "declval.hpp"
//----------------------------------------------------------------------------//
// //
// C++03 implementation of //
// 20.6.7 Other transformations [meta.trans.other] //
// Written by Howard Hinnant //
// Adapted for Boost by Beman Dawes, Vicente Botet and Jeffrey Hellrung //
// //
//----------------------------------------------------------------------------//
namespace boost_ex {
// prototype
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
template<typename... T>
struct common_type;
#else // or no specialization
template <class T, class U = void, class V = void>
struct common_type
{
public:
typedef typename common_type<typename common_type<T, U>::type, V>::type type;
};
#endif
// 1 arg
template<typename T>
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
struct common_type<T>
#else
struct common_type<T, void, void>
#endif
{
BOOST_EX_COMMON_TYPE_STATIC_ASSERT(sizeof(T) > 0, BOOST_EX_COMMON_TYPE_MUST_BE_A_COMPLE_TYPE, (T));
public:
typedef T type;
};
// 2 args
namespace type_traits_detail {
template <class T, class U>
struct common_type_2
{
private:
BOOST_EX_COMMON_TYPE_STATIC_ASSERT(sizeof(T) > 0, BOOST_EX_COMMON_TYPE_MUST_BE_A_COMPLE_TYPE, (T));
BOOST_EX_COMMON_TYPE_STATIC_ASSERT(sizeof(U) > 0, BOOST_EX_COMMON_TYPE_MUST_BE_A_COMPLE_TYPE, (U));
static bool declval_bool(); // workaround gcc bug; not required by std
static typename add_rvalue_reference<T>::type declval_T(); // workaround gcc bug; not required by std
static typename add_rvalue_reference<U>::type declval_U(); // workaround gcc bug; not required by std
#if !defined(BOOST_NO_DECLTYPE)
public:
typedef decltype(declval<bool>() ? declval<T>() : declval<U>()) type;
#elif defined(BOOST_EX_COMMON_TYPE_DONT_USE_TYPEOF)
public:
typedef typename detail_type_traits_common_type::common_type_impl<
typename remove_cv<T>::type,
typename remove_cv<U>::type
>::type type;
#else
public:
//~ typedef BOOST_TYPEOF_TPL(declval_bool() ? declval_T() : declval_U()) type;
typedef BOOST_TYPEOF_TPL(declval<bool>() ? declval<T>() : declval<U>()) type;
#endif
};
template <class T>
struct common_type_2<T, T>
{
typedef T type;
};
}
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
template <class T, class U>
struct common_type<T, U>
#else
template <class T, class U>
struct common_type<T, U, void>
#endif
: type_traits_detail::common_type_2<T,U>
{ };
// 3 or more args
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
template<typename T, typename U, typename... V>
struct common_type<T, U, V...> {
public:
typedef typename common_type<typename common_type<T, U>::type, V...>::type type;
};
#endif
} // namespace boost_ex
#endif // BOOST_TYPE_TRAITS_EXT_COMMON_TYPE_HPP