New implementation of common_type.

This commit is contained in:
Peter Dimov
2015-06-07 19:12:55 +03:00
parent e31d0ab7bd
commit ad1ddddaf4
8 changed files with 696 additions and 475 deletions

View File

@@ -1,163 +1,87 @@
// common_type.hpp ---------------------------------------------------------//
// Copyright 2008 Howard Hinnant
// Copyright 2008 Beman Dawes
#ifndef BOOST_TYPE_TRAITS_COMMON_TYPE_HPP_INCLUDED
#define BOOST_TYPE_TRAITS_COMMON_TYPE_HPP_INCLUDED
//
// Copyright 2015 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#ifndef BOOST_TYPE_TRAITS_COMMON_TYPE_HPP
#define BOOST_TYPE_TRAITS_COMMON_TYPE_HPP
#include <boost/config.hpp>
#include <boost/static_assert.hpp>
#if defined(__SUNPRO_CC) && !defined(BOOST_COMMON_TYPE_DONT_USE_TYPEOF)
# define BOOST_COMMON_TYPE_DONT_USE_TYPEOF
#endif
#if defined(__IBMCPP__) && !defined(BOOST_COMMON_TYPE_DONT_USE_TYPEOF)
# define BOOST_COMMON_TYPE_DONT_USE_TYPEOF
#endif
#if defined(__GNUC__) && !defined(BOOST_COMMON_TYPE_DONT_USE_TYPEOF)
// All supported GCC versions (and emulations thereof) support __typeof__
#define BOOST_COMMON_TYPE_USE_TYPEOF
#endif
//----------------------------------------------------------------------------//
#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_COMMON_TYPE_ARITY)
#define BOOST_COMMON_TYPE_ARITY 3
#endif
//----------------------------------------------------------------------------//
#if !defined(BOOST_NO_CXX11_DECLTYPE)
#include <boost/utility/declval.hpp>
#elif defined(BOOST_COMMON_TYPE_USE_TYPEOF)
#include <boost/type_traits/add_rvalue_reference.hpp>
#elif defined(BOOST_COMMON_TYPE_DONT_USE_TYPEOF)
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/detail/common_type_imp.hpp>
#else
#include <boost/typeof/typeof.hpp> // boost wonders never cease!
#include <boost/type_traits/detail/common_type_imp.hpp>
#include <boost/type_traits/add_rvalue_reference.hpp>
#endif
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/decay.hpp>
#include <boost/utility/declval.hpp>
//----------------------------------------------------------------------------//
// //
// C++03 implementation of //
// 20.9.7.6 Other transformations [meta.trans.other] //
// Written by Howard Hinnant //
// Adapted for Boost by Beman Dawes, Vicente Botet and Jeffrey Hellrung //
// //
//----------------------------------------------------------------------------//
namespace boost {
namespace type_traits_detail {
template <class T>
struct std_decay: boost::remove_cv<
typename boost::decay<T>::type> {};
}
// prototype
#if !defined(BOOST_NO_CXX11_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;
};
#if defined(BOOST_NO_CXX11_DECLTYPE)
#include <boost/type_traits/detail/common_type_impl.hpp>
#endif
namespace boost
{
// variadic common_type
// 1 arg
template<typename T>
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
struct common_type<T>
template<class... T> struct common_type
{
};
template<class T1, class T2, class... T>
struct common_type<T1, T2, T...>: common_type<typename common_type<T1, T2>::type, T...>
{
};
#else
struct common_type<T, void, void>
#endif
{
BOOST_STATIC_ASSERT_MSG(sizeof(T) > 0, "The template arguments to common_type must be complete types");
public:
typedef typename type_traits_detail::std_decay<T>::type type;
};
template<
class T1 = void, class T2 = void, class T3 = void,
class T4 = void, class T5 = void, class T6 = void,
class T7 = void, class T8 = void, class T9 = void
>
struct common_type: common_type<typename common_type<T1, T2>::type, T3, T4, T5, T6, T7, T8, T9>
{
};
// 2 args
namespace type_traits_detail {
#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class T, class U>
struct common_type_2
{
private:
BOOST_STATIC_ASSERT_MSG(sizeof(T) > 0, "The template arguments to common_type must be complete types");
BOOST_STATIC_ASSERT_MSG(sizeof(U) > 0, "The template arguments to common_type must be complete types");
// one argument
template<class T> struct common_type<T>: boost::decay<T>
{
};
// two arguments
namespace type_traits_detail
{
// binary common_type
#if !defined(BOOST_NO_CXX11_DECLTYPE)
public:
typedef typename std_decay<decltype(declval<bool>() ? declval<T>() : declval<U>())>::type type;
#elif defined(BOOST_COMMON_TYPE_USE_TYPEOF)
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
static typename add_rvalue_reference<bool>::type declval_b();
public:
typedef typename std_decay<__typeof__(declval_b() ? declval_T() : declval_U())>::type type;
#elif defined(BOOST_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
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
static typename add_rvalue_reference<bool>::type declval_b();
public:
typedef typename std_decay<BOOST_TYPEOF_TPL(declval_b() ? declval_T() : declval_U())>::type type;
#endif
#if defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ == 3
public:
void public_dummy_function_just_to_silence_warning();
#endif
};
template<class T1, class T2> struct common_type_impl: boost::decay<decltype( boost::declval<bool>()? boost::declval<T1>(): boost::declval<T2>() )>
{
};
template <class T>
struct common_type_2<T, T>
{
typedef typename type_traits_detail::std_decay<T>::type type;
};
}
#endif // #if !defined(BOOST_NO_CXX11_DECLTYPE)
#if !defined(BOOST_NO_CXX11_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
: public type_traits_detail::common_type_2<T,U>
{ };
// decay helper
template<class T1, class T2, class T1d = typename boost::decay<T1>::type, class T2d = typename boost::decay<T2>::type> struct common_type_decay_helper: boost::common_type<T1d, T2d>
{
};
// 3 or more args
#if !defined(BOOST_NO_CXX11_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
template<class T1, class T2> struct common_type_decay_helper<T1, T2, T1, T2>: common_type_impl<T1, T2>
{
};
#endif // BOOST_TYPE_TRAITS_COMMON_TYPE_HPP
} // type_traits_detail
template<class T1, class T2> struct common_type<T1, T2>: type_traits_detail::common_type_decay_helper<T1, T2>
{
};
} // namespace boost
#endif // #ifndef BOOST_TYPE_TRAITS_COMMON_TYPE_HPP_INCLUDED

View File

@@ -0,0 +1,34 @@
#ifndef BOOST_TYPE_TRAITS_COPY_CV_HPP_INCLUDED
#define BOOST_TYPE_TRAITS_COPY_CV_HPP_INCLUDED
//
// Copyright 2015 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#include <boost/type_traits/is_const.hpp>
#include <boost/type_traits/is_volatile.hpp>
#include <boost/type_traits/add_const.hpp>
#include <boost/type_traits/add_volatile.hpp>
#include <boost/type_traits/conditional.hpp>
namespace boost
{
template<class T, class U> struct copy_cv
{
private:
typedef typename boost::conditional<boost::is_const<U>::value, typename boost::add_const<T>::type, T>::type CT;
public:
typedef typename boost::conditional<boost::is_volatile<U>::value, typename boost::add_volatile<CT>::type, CT>::type type;
};
} // namespace boost
#endif // #ifndef BOOST_TYPE_TRAITS_COPY_CV_HPP_INCLUDED

View File

@@ -0,0 +1,212 @@
#ifndef BOOST_TYPE_TRAITS_DETAIL_COMMON_ARITHMETIC_TYPE_HPP_INCLUDED
#define BOOST_TYPE_TRAITS_DETAIL_COMMON_ARITHMETIC_TYPE_HPP_INCLUDED
//
// Copyright 2015 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#include <boost/config.hpp>
namespace boost
{
namespace type_traits_detail
{
template<int I> struct arithmetic_type;
// Types bool, char, char16_t, char32_t, wchar_t,
// and the signed and unsigned integer types are
// collectively called integral types
template<> struct arithmetic_type<1>
{
typedef bool type;
typedef char (&result_type) [1];
};
template<> struct arithmetic_type<2>
{
typedef char type;
typedef char (&result_type) [2];
};
template<> struct arithmetic_type<3>
{
typedef wchar_t type;
typedef char (&result_type) [3];
};
// There are five standard signed integer types:
// <20>signed char<61>, <20>short int<6E>, <20>int<6E>, <20>long int<6E>, and <20>long long int<6E>.
template<> struct arithmetic_type<4>
{
typedef signed char type;
typedef char (&result_type) [4];
};
template<> struct arithmetic_type<5>
{
typedef short type;
typedef char (&result_type) [5];
};
template<> struct arithmetic_type<6>
{
typedef int type;
typedef char (&result_type) [6];
};
template<> struct arithmetic_type<7>
{
typedef long type;
typedef char (&result_type) [7];
};
template<> struct arithmetic_type<8>
{
typedef boost::long_long_type type;
typedef char (&result_type) [8];
};
// For each of the standard signed integer types, there exists a corresponding
// (but different) standard unsigned integer type: <20>unsigned char<61>, <20>unsigned short int<6E>,
// <20>unsigned int<6E>, <20>unsigned long int<6E>, and <20>unsigned long long int<6E>
template<> struct arithmetic_type<9>
{
typedef unsigned char type;
typedef char (&result_type) [9];
};
template<> struct arithmetic_type<10>
{
typedef unsigned short type;
typedef char (&result_type) [10];
};
template<> struct arithmetic_type<11>
{
typedef unsigned int type;
typedef char (&result_type) [11];
};
template<> struct arithmetic_type<12>
{
typedef unsigned long type;
typedef char (&result_type) [12];
};
template<> struct arithmetic_type<13>
{
typedef boost::ulong_long_type type;
typedef char (&result_type) [13];
};
// There are three floating point types: float, double, and long double.
template<> struct arithmetic_type<14>
{
typedef float type;
typedef char (&result_type) [14];
};
template<> struct arithmetic_type<15>
{
typedef double type;
typedef char (&result_type) [15];
};
template<> struct arithmetic_type<16>
{
typedef long double type;
typedef char (&result_type) [16];
};
#if !defined( BOOST_NO_CXX11_CHAR16_T )
template<> struct arithmetic_type<17>
{
typedef char16_t type;
typedef char (&result_type) [17];
};
#endif
#if !defined( BOOST_NO_CXX11_CHAR32_T )
template<> struct arithmetic_type<18>
{
typedef char32_t type;
typedef char (&result_type) [18];
};
#endif
#if defined( BOOST_HAS_INT128 )
template<> struct arithmetic_type<19>
{
typedef __int128 type;
typedef char (&result_type) [19];
};
template<> struct arithmetic_type<20>
{
typedef unsigned __int128 type;
typedef char (&result_type) [20];
};
#endif
template<class T, class U> class common_arithmetic_type
{
private:
static arithmetic_type<1>::result_type select( arithmetic_type<1>::type );
static arithmetic_type<2>::result_type select( arithmetic_type<2>::type );
static arithmetic_type<3>::result_type select( arithmetic_type<3>::type );
static arithmetic_type<4>::result_type select( arithmetic_type<4>::type );
static arithmetic_type<5>::result_type select( arithmetic_type<5>::type );
static arithmetic_type<6>::result_type select( arithmetic_type<6>::type );
static arithmetic_type<7>::result_type select( arithmetic_type<7>::type );
static arithmetic_type<8>::result_type select( arithmetic_type<8>::type );
static arithmetic_type<9>::result_type select( arithmetic_type<9>::type );
static arithmetic_type<10>::result_type select( arithmetic_type<10>::type );
static arithmetic_type<11>::result_type select( arithmetic_type<11>::type );
static arithmetic_type<12>::result_type select( arithmetic_type<12>::type );
static arithmetic_type<13>::result_type select( arithmetic_type<13>::type );
static arithmetic_type<14>::result_type select( arithmetic_type<14>::type );
static arithmetic_type<15>::result_type select( arithmetic_type<15>::type );
static arithmetic_type<16>::result_type select( arithmetic_type<16>::type );
#if !defined( BOOST_NO_CXX11_CHAR16_T )
static arithmetic_type<17>::result_type select( arithmetic_type<17>::type );
#endif
#if !defined( BOOST_NO_CXX11_CHAR32_T )
static arithmetic_type<18>::result_type select( arithmetic_type<18>::type );
#endif
#if defined( BOOST_HAS_INT128 )
static arithmetic_type<19>::result_type select( arithmetic_type<19>::type );
static arithmetic_type<20>::result_type select( arithmetic_type<20>::type );
#endif
static bool cond();
public:
typedef typename arithmetic_type< sizeof(select( cond()? T(): U() )) >::type type;
};
} // namespace type_traits_detail
} // namespace boost
#endif // #ifndef BOOST_TYPE_TRAITS_DETAIL_COMMON_ARITHMETIC_TYPE_HPP_INCLUDED

View File

@@ -1,333 +0,0 @@
/*******************************************************************************
* boost/type_traits/detail/common_type_imp.hpp
*
* Copyright 2010, Jeffrey Hellrung.
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
* struct boost::common_type<T,U>
*
* common_type<T,U>::type is the type of the expression
* b() ? x() : y()
* where b() returns a bool, x() has return type T, and y() has return type U.
* See
* http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2661.htm#common_type
*
* Note that this evaluates to void if one or both of T and U is void.
******************************************************************************/
#ifndef BOOST_TYPE_TRAITS_DETAIL_COMMON_TYPE_IMP_HPP
#define BOOST_TYPE_TRAITS_DETAIL_COMMON_TYPE_IMP_HPP
#include <cstddef>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/begin_end.hpp>
#include <boost/mpl/contains.hpp>
#include <boost/mpl/copy.hpp>
#include <boost/mpl/deref.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/inserter.hpp>
#include <boost/mpl/next.hpp>
#include <boost/mpl/or.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/push_back.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/vector/vector0.hpp>
#include <boost/mpl/vector/vector10.hpp>
#include <boost/type_traits/integral_constant.hpp>
#include <boost/type_traits/is_enum.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/make_signed.hpp>
#include <boost/type_traits/make_unsigned.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/utility/declval.hpp>
namespace boost
{
namespace detail_type_traits_common_type
{
/*******************************************************************************
* struct propagate_cv< From, To >
*
* This metafunction propagates cv-qualifiers on type From to type To.
******************************************************************************/
template< class From, class To >
struct propagate_cv
{ typedef To type; };
template< class From, class To >
struct propagate_cv< const From, To >
{ typedef To const type; };
template< class From, class To >
struct propagate_cv< volatile From, To >
{ typedef To volatile type; };
template< class From, class To >
struct propagate_cv< const volatile From, To >
{ typedef To const volatile type; };
/*******************************************************************************
* struct is_integral_or_enum<T>
*
* This metafunction determines if T is an integral type which can be made
* signed or unsigned.
******************************************************************************/
template< class T >
struct is_integral_or_enum
: public mpl::or_< is_integral<T>, is_enum<T> >
{ };
template<>
struct is_integral_or_enum< bool >
: public false_type
{ };
/*******************************************************************************
* struct make_unsigned_soft<T>
* struct make_signed_soft<T>
*
* These metafunction are identical to make_unsigned and make_signed,
* respectively, except for special-casing bool.
******************************************************************************/
template< class T >
struct make_unsigned_soft
: public make_unsigned<T>
{ };
template<>
struct make_unsigned_soft< bool >
{ typedef bool type; };
template< class T >
struct make_signed_soft
: public make_signed<T>
{ };
template<>
struct make_signed_soft< bool >
{ typedef bool type; };
/*******************************************************************************
* struct sizeof_t<N>
* typedef ... yes_type
* typedef ... no_type
*
* These types are integral players in the use of the "sizeof trick", i.e., we
* can distinguish overload selection by inspecting the size of the return type
* of the overload.
******************************************************************************/
template< std::size_t N > struct sizeof_t { char _dummy[N]; };
typedef sizeof_t<1> yes_type;
typedef sizeof_t<2> no_type;
BOOST_MPL_ASSERT_RELATION( sizeof( yes_type ), ==, 1 );
BOOST_MPL_ASSERT_RELATION( sizeof( no_type ), ==, 2 );
/*******************************************************************************
* rvalue_test(T&) -> no_type
* rvalue_test(...) -> yes_type
*
* These overloads are used to determine the rvalue-ness of an expression.
******************************************************************************/
template< class T > no_type rvalue_test(T&);
yes_type rvalue_test(...);
/*******************************************************************************
* struct conversion_test_overloads< Sequence >
*
* This struct has multiple overloads of the static member function apply, each
* one taking a single parameter of a type within the Boost.MPL sequence
* Sequence. Each such apply overload has a return type with sizeof equal to
* one plus the index of the parameter type within Sequence. Thus, we can
* deduce the type T of an expression as long as we can generate a finite set of
* candidate types containing T via these apply overloads and the "sizeof
* trick".
******************************************************************************/
template< class First, class Last, std::size_t Index >
struct conversion_test_overloads_iterate
: public conversion_test_overloads_iterate<
typename mpl::next< First >::type, Last, Index + 1
>
{
using conversion_test_overloads_iterate<
typename mpl::next< First >::type, Last, Index + 1
>::apply;
static sizeof_t< Index + 1 >
apply(typename mpl::deref< First >::type);
};
template< class Last, std::size_t Index >
struct conversion_test_overloads_iterate< Last, Last, Index >
{ static sizeof_t< Index + 1 > apply(...); };
template< class Sequence >
struct conversion_test_overloads
: public conversion_test_overloads_iterate<
typename mpl::begin< Sequence >::type,
typename mpl::end< Sequence >::type,
0
>
{ };
/*******************************************************************************
* struct select< Sequence, Index >
*
* select is synonymous with mpl::at_c unless Index equals the size of the
* Boost.MPL Sequence, in which case this evaluates to void.
******************************************************************************/
template<
class Sequence, int Index,
int N = mpl::size< Sequence >::value
>
struct select
: public mpl::at_c< Sequence, Index >
{ };
template< class Sequence, int N >
struct select< Sequence, N, N >
{ typedef void type; };
/*******************************************************************************
* class deduce_common_type< T, U, NominalCandidates >
* struct nominal_candidates<T,U>
* struct common_type_dispatch_on_rvalueness<T,U>
* struct common_type_impl<T,U>
*
* These classes and structs implement the logic behind common_type, which goes
* roughly as follows. Let C be the type of the conditional expression
* declval< bool >() ? declval<T>() : declval<U>()
* if C is an rvalue, then:
* let T' and U' be T and U stripped of reference- and cv-qualifiers
* if T' and U' are pointer types, say, T' = V* and U' = W*, then:
* define the set of NominalCandidates to be
* { V*, W*, V'*, W'* }
* where V' is V with whatever cv-qualifiers are on W, and W' is W
* with whatever cv-qualifiers are on V
* else if T' and U' are both integral or enum types, then:
* define the set of NominalCandidates to be
* {
* unsigned_soft(T'),
* unsigned_soft(U'),
* signed_soft(T'),
* signed_soft(U'),
* T',
* U',
* unsigned int,
* int
* }
* where unsigned_soft(X) is make_unsigned_soft<X>::type and
* signed_soft(X) is make_signed_soft<X>::type (these are all
* generally necessary to cover the various integral promotion cases)
* else
* define the set of NominalCandidates to be
* { T', U' }
* else
* let V and W be T and U stripped of reference-qualifiers
* define the set of NominalCandidates to be
* { V&, W&, V'&, W'& }
* where V' is V with whatever cv-qualifiers are on W, and W' is W with
* whatever cv-qualifiers are on V
* define the set of Candidates to be equal to the set of NominalCandidates with
* duplicates removed, and use this set of Candidates to determine C using the
* conversion_test_overloads struct
******************************************************************************/
template< class T, class U, class NominalCandidates >
class deduce_common_type
{
typedef typename mpl::copy<
NominalCandidates,
mpl::inserter<
mpl::vector0<>,
mpl::if_<
mpl::contains< mpl::_1, mpl::_2 >,
mpl::_1,
mpl::push_back< mpl::_1, mpl::_2 >
>
>
>::type candidate_types;
static const int best_candidate_index =
sizeof( conversion_test_overloads< candidate_types >::apply(
declval< bool >() ? declval<T>() : declval<U>()
) ) - 1;
public:
typedef typename select< candidate_types, best_candidate_index >::type type;
};
template<
class T, class U,
class V = typename remove_cv< typename remove_reference<T>::type >::type,
class W = typename remove_cv< typename remove_reference<U>::type >::type,
bool = is_integral_or_enum<V>::value && is_integral_or_enum<W>::value
>
struct nominal_candidates
{ typedef mpl::vector2<V,W> type; };
template< class T, class U, class V, class W >
struct nominal_candidates< T, U, V, W, true >
{
typedef boost::mpl::vector8<
typename make_unsigned_soft<V>::type,
typename make_unsigned_soft<W>::type,
typename make_signed_soft<V>::type,
typename make_signed_soft<W>::type,
V, W, unsigned int, int
> type;
};
template< class T, class U, class V, class W >
struct nominal_candidates< T, U, V*, W*, false >
{
typedef mpl::vector4<
V*, W*,
typename propagate_cv<W,V>::type *,
typename propagate_cv<V,W>::type *
> type;
};
template<class T, class U, bool b>
struct common_type_dispatch_on_rvalueness
: public deduce_common_type< T, U, typename nominal_candidates<T,U>::type >
{ };
template< class T, class U >
struct common_type_dispatch_on_rvalueness< T, U, false >
{
private:
typedef typename remove_reference<T>::type unrefed_T_type;
typedef typename remove_reference<U>::type unrefed_U_type;
public:
typedef typename deduce_common_type<
T, U,
mpl::vector4<
unrefed_T_type &,
unrefed_U_type &,
typename propagate_cv< unrefed_U_type, unrefed_T_type >::type &,
typename propagate_cv< unrefed_T_type, unrefed_U_type >::type &
>
>::type type;
};
template< class T, class U >
struct common_type_impl
: public common_type_dispatch_on_rvalueness<T,U, sizeof( ::boost::detail_type_traits_common_type::rvalue_test(
declval< bool >() ? declval<T>() : declval<U>() ) ) == sizeof( yes_type ) >
{ };
template< class T > struct common_type_impl< T, void > { typedef void type; };
template< class T > struct common_type_impl< void, T > { typedef void type; };
template<> struct common_type_impl< void, void > { typedef void type; };
} // namespace detail_type_traits_common_type
} // namespace boost
#endif // BOOST_TYPE_TRAITS_DETAIL_COMMON_TYPE_HPP

View File

@@ -0,0 +1,112 @@
#ifndef BOOST_TYPE_TRAITS_DETAIL_COMMON_TYPE_HPP_INCLUDED
#define BOOST_TYPE_TRAITS_DETAIL_COMMON_TYPE_HPP_INCLUDED
//
// Copyright 2015 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#include <boost/type_traits/detail/common_arithmetic_type.hpp>
#include <boost/type_traits/detail/composite_pointer_type.hpp>
#include <boost/type_traits/detail/composite_member_pointer_type.hpp>
#include <boost/type_traits/tp_identity.hpp>
#include <boost/type_traits/is_lvalue_reference.hpp>
#include <boost/type_traits/is_class.hpp>
#include <boost/type_traits/is_union.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
#include <boost/type_traits/is_enum.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/type_traits/is_member_pointer.hpp>
#include <boost/type_traits/conditional.hpp>
#include <boost/type_traits/decay.hpp>
namespace boost
{
namespace type_traits_detail
{
// the arguments to common_type_impl have already been passed through decay<>
template<class T, class U> struct common_type_impl;
// same type
template<class T> struct common_type_impl<T, T>
{
typedef T type;
};
// one of the operands is a class type, try conversions in both directions
template<class T, class U> struct ct_class
{
BOOST_STATIC_CONSTANT( bool, ct = boost::is_class<T>::value || boost::is_union<T>::value );
BOOST_STATIC_CONSTANT( bool, cu = boost::is_class<U>::value || boost::is_union<U>::value );
BOOST_STATIC_CONSTANT( bool, value = ct || cu );
};
template<class T, class U> struct common_type_impl3;
template<class T, class U> struct common_type_class: public boost::conditional<
boost::is_convertible<T, U>::value && !boost::is_convertible<U, T>::value,
boost::tp_identity<U>,
typename boost::conditional<
boost::is_convertible<U, T>::value && !boost::is_convertible<T, U>::value,
boost::tp_identity<T>,
common_type_impl3<T, U>
>::type
>::type
{
};
template<class T, class U> struct common_type_impl: public boost::conditional<
ct_class<T, U>::value,
common_type_class<T, U>,
common_type_impl3<T, U> >::type
{
};
// pointers
template<class T, class U> struct common_type_impl4;
template<class T, class U> struct common_type_impl3: public boost::conditional<
boost::is_pointer<T>::value || boost::is_pointer<U>::value,
composite_pointer_type<T, U>,
common_type_impl4<T, U> >::type
{
};
// pointers to members
template<class T, class U> struct common_type_impl5;
template<class T, class U> struct common_type_impl4: public boost::conditional<
boost::is_member_pointer<T>::value || boost::is_member_pointer<U>::value,
composite_member_pointer_type<T, U>,
common_type_impl5<T, U> >::type
{
};
// arithmetic types (including class types w/ conversions to arithmetic and enums)
template<class T, class U> struct common_type_impl5: public common_arithmetic_type<T, U>
{
};
} // namespace type_traits_detail
} // namespace boost
#endif // #ifndef BOOST_TYPE_TRAITS_DETAIL_COMMON_TYPE_HPP_INCLUDED

View File

@@ -0,0 +1,105 @@
#ifndef BOOST_TYPE_TRAITS_DETAIL_COMPOSITE_MEMBER_POINTER_TYPE_HPP_INCLUDED
#define BOOST_TYPE_TRAITS_DETAIL_COMPOSITE_MEMBER_POINTER_TYPE_HPP_INCLUDED
//
// Copyright 2015 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#include <boost/type_traits/detail/composite_pointer_type.hpp>
#include <boost/type_traits/remove_pointer.hpp>
#include <boost/type_traits/is_base_of.hpp>
#include <boost/type_traits/conditional.hpp>
#include <boost/config.hpp>
#include <cstddef>
namespace boost
{
namespace type_traits_detail
{
template<class T, class U> struct composite_member_pointer_type;
// nullptr_t
#if !defined( BOOST_NO_CXX11_NULLPTR )
#if !defined( BOOST_NO_CXX11_DECLTYPE ) && ( ( defined( __clang__ ) && !defined( _LIBCPP_VERSION ) ) || defined( __INTEL_COMPILER ) )
template<class C, class T> struct composite_member_pointer_type<T C::*, decltype(nullptr)>
{
typedef T C::* type;
};
template<class C, class T> struct composite_member_pointer_type<decltype(nullptr), T C::*>
{
typedef T C::* type;
};
template<> struct composite_member_pointer_type<decltype(nullptr), decltype(nullptr)>
{
typedef decltype(nullptr) type;
};
#else
template<class C, class T> struct composite_member_pointer_type<T C::*, std::nullptr_t>
{
typedef T C::* type;
};
template<class C, class T> struct composite_member_pointer_type<std::nullptr_t, T C::*>
{
typedef T C::* type;
};
template<> struct composite_member_pointer_type<std::nullptr_t, std::nullptr_t>
{
typedef std::nullptr_t type;
};
#endif
#endif // !defined( BOOST_NO_CXX11_NULLPTR )
template<class C1, class C2> struct common_member_class;
template<class C> struct common_member_class<C, C>
{
typedef C type;
};
template<class C1, class C2> struct common_member_class
{
typedef typename boost::conditional<
boost::is_base_of<C1, C2>::value,
C2,
typename boost::conditional<boost::is_base_of<C2, C1>::value, C1, void>::type
>::type type;
};
template<class C1, class T1, class C2, class T2> struct composite_member_pointer_type<T1 C1::*, T2 C2::*>
{
private:
typedef typename composite_pointer_type<T1*, T2*>::type CPT;
typedef typename boost::remove_pointer<CPT>::type CT;
typedef typename common_member_class<C1, C2>::type CB;
public:
typedef CT CB::* type;
};
} // namespace type_traits_detail
} // namespace boost
#endif // #ifndef BOOST_TYPE_TRAITS_DETAIL_COMPOSITE_MEMBER_POINTER_TYPE_HPP_INCLUDED

View File

@@ -0,0 +1,145 @@
#ifndef BOOST_TYPE_TRAITS_DETAIL_COMPOSITE_POINTER_TYPE_HPP_INCLUDED
#define BOOST_TYPE_TRAITS_DETAIL_COMPOSITE_POINTER_TYPE_HPP_INCLUDED
//
// Copyright 2015 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#include <boost/type_traits/copy_cv.hpp>
#include <boost/type_traits/tp_identity.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_void.hpp>
#include <boost/type_traits/is_base_of.hpp>
#include <boost/config.hpp>
#include <cstddef>
namespace boost
{
namespace type_traits_detail
{
template<class T, class U> struct composite_pointer_type;
// same type
template<class T> struct composite_pointer_type<T*, T*>
{
typedef T* type;
};
// nullptr_t
#if !defined( BOOST_NO_CXX11_NULLPTR )
#if !defined( BOOST_NO_CXX11_DECLTYPE ) && ( ( defined( __clang__ ) && !defined( _LIBCPP_VERSION ) ) || defined( __INTEL_COMPILER ) )
template<class T> struct composite_pointer_type<T*, decltype(nullptr)>
{
typedef T* type;
};
template<class T> struct composite_pointer_type<decltype(nullptr), T*>
{
typedef T* type;
};
template<> struct composite_pointer_type<decltype(nullptr), decltype(nullptr)>
{
typedef decltype(nullptr) type;
};
#else
template<class T> struct composite_pointer_type<T*, std::nullptr_t>
{
typedef T* type;
};
template<class T> struct composite_pointer_type<std::nullptr_t, T*>
{
typedef T* type;
};
template<> struct composite_pointer_type<std::nullptr_t, std::nullptr_t>
{
typedef std::nullptr_t type;
};
#endif
#endif // !defined( BOOST_NO_CXX11_NULLPTR )
namespace detail
{
template<class T, class U> struct has_common_pointee
{
private:
typedef typename boost::remove_cv<T>::type T2;
typedef typename boost::remove_cv<U>::type U2;
public:
BOOST_STATIC_CONSTANT( bool, value =
(boost::is_same<T2, U2>::value)
|| boost::is_void<T2>::value
|| boost::is_void<U2>::value
|| (boost::is_base_of<T2, U2>::value)
|| (boost::is_base_of<U2, T2>::value) );
};
template<class T, class U> struct common_pointee
{
private:
typedef typename boost::remove_cv<T>::type T2;
typedef typename boost::remove_cv<U>::type U2;
public:
typedef typename boost::conditional<
boost::is_same<T2, U2>::value || boost::is_void<T2>::value || boost::is_base_of<T2, U2>::value,
typename boost::copy_cv<T, U>::type,
typename boost::copy_cv<U, T>::type
>::type type;
};
template<class T, class U> struct composite_pointer_impl
{
private:
typedef typename boost::remove_cv<T>::type T2;
typedef typename boost::remove_cv<U>::type U2;
public:
typedef typename boost::copy_cv<typename boost::copy_cv<typename composite_pointer_type<T2, U2>::type const, T>::type, U>::type type;
};
} // detail
template<class T, class U> struct composite_pointer_type<T*, U*>
{
typedef typename boost::conditional<
detail::has_common_pointee<T, U>::value,
detail::common_pointee<T, U>,
detail::composite_pointer_impl<T, U>
>::type::type * type;
};
} // namespace type_traits_detail
} // namespace boost
#endif // #ifndef BOOST_TYPE_TRAITS_DETAIL_COMPOSITE_POINTER_TYPE_HPP_INCLUDED

View File

@@ -0,0 +1,22 @@
#ifndef BOOST_TYPE_TRAITS_TP_IDENTITY_HPP_INCLUDED
#define BOOST_TYPE_TRAITS_TP_IDENTITY_HPP_INCLUDED
//
// Copyright 2015 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
namespace boost
{
template<class T> struct tp_identity
{
typedef T type;
};
} // namespace boost
#endif // #ifndef BOOST_TYPE_TRAITS_TP_IDENTITY_HPP_INCLUDED