1 // common_type.hpp ---------------------------------------------------------//
3 // Copyright 2008 Howard Hinnant
4 // Copyright 2008 Beman Dawes
6 // Distributed under the Boost Software License, Version 1.0.
7 // See http://www.boost.org/LICENSE_1_0.txt
9 #ifndef BOOST_TYPE_TRAITS_COMMON_TYPE_HPP
10 #define BOOST_TYPE_TRAITS_COMMON_TYPE_HPP
12 #include <boost/config.hpp>
15 # define BOOST_COMMON_TYPE_DONT_USE_TYPEOF
18 # define BOOST_COMMON_TYPE_DONT_USE_TYPEOF
21 //----------------------------------------------------------------------------//
22 #if defined(BOOST_NO_VARIADIC_TEMPLATES)
23 #define BOOST_COMMON_TYPE_ARITY 3
26 //----------------------------------------------------------------------------//
27 #if defined(BOOST_NO_DECLTYPE) && !defined(BOOST_COMMON_TYPE_DONT_USE_TYPEOF)
28 #define BOOST_TYPEOF_SILENT
29 #include <boost/typeof/typeof.hpp> // boost wonders never cease!
32 //----------------------------------------------------------------------------//
33 #ifndef BOOST_NO_STATIC_ASSERT
34 #define BOOST_COMMON_TYPE_STATIC_ASSERT(CND, MSG, TYPES) static_assert(CND,MSG)
35 #elif defined(BOOST_COMMON_TYPE_USES_MPL_ASSERT)
36 #include <boost/mpl/assert.hpp>
37 #include <boost/mpl/bool.hpp>
38 #define BOOST_COMMON_TYPE_STATIC_ASSERT(CND, MSG, TYPES) \
39 BOOST_MPL_ASSERT_MSG(boost::mpl::bool_< (CND) >::type::value, MSG, TYPES)
41 #include <boost/static_assert.hpp>
42 #define BOOST_COMMON_TYPE_STATIC_ASSERT(CND, MSG, TYPES) BOOST_STATIC_ASSERT(CND)
45 #if !defined(BOOST_NO_STATIC_ASSERT) || !defined(BOOST_COMMON_TYPE_USES_MPL_ASSERT)
46 #define BOOST_COMMON_TYPE_MUST_BE_A_COMPLE_TYPE "must be complete type"
49 #if defined(BOOST_NO_DECLTYPE) && defined(BOOST_COMMON_TYPE_DONT_USE_TYPEOF)
50 #include <boost/type_traits/detail/common_type_imp.hpp>
51 #include <boost/type_traits/remove_cv.hpp>
53 #include <boost/mpl/if.hpp>
54 #include <boost/utility/declval.hpp>
55 #include <boost/type_traits/add_rvalue_reference.hpp>
57 //----------------------------------------------------------------------------//
59 // C++03 implementation of //
60 // 20.6.7 Other transformations [meta.trans.other] //
61 // Written by Howard Hinnant //
62 // Adapted for Boost by Beman Dawes, Vicente Botet and Jeffrey Hellrung //
64 //----------------------------------------------------------------------------//
69 #if !defined(BOOST_NO_VARIADIC_TEMPLATES)
70 template<typename... T>
72 #else // or no specialization
73 template <class T, class U = void, class V = void>
77 typedef typename common_type<typename common_type<T, U>::type, V>::type type;
84 #if !defined(BOOST_NO_VARIADIC_TEMPLATES)
87 struct common_type<T, void, void>
91 BOOST_COMMON_TYPE_STATIC_ASSERT(sizeof(T) > 0, BOOST_COMMON_TYPE_MUST_BE_A_COMPLE_TYPE, (T));
97 namespace type_traits_detail {
99 template <class T, class U>
103 BOOST_COMMON_TYPE_STATIC_ASSERT(sizeof(T) > 0, BOOST_COMMON_TYPE_MUST_BE_A_COMPLE_TYPE, (T));
104 BOOST_COMMON_TYPE_STATIC_ASSERT(sizeof(U) > 0, BOOST_COMMON_TYPE_MUST_BE_A_COMPLE_TYPE, (U));
105 static bool declval_bool(); // workaround gcc bug; not required by std
106 static typename add_rvalue_reference<T>::type declval_T(); // workaround gcc bug; not required by std
107 static typename add_rvalue_reference<U>::type declval_U(); // workaround gcc bug; not required by std
108 static typename add_rvalue_reference<bool>::type declval_b();
110 #if !defined(BOOST_NO_DECLTYPE)
112 typedef decltype(declval<bool>() ? declval<T>() : declval<U>()) type;
113 #elif defined(BOOST_COMMON_TYPE_DONT_USE_TYPEOF)
115 typedef typename detail_type_traits_common_type::common_type_impl<
116 typename remove_cv<T>::type,
117 typename remove_cv<U>::type
121 typedef BOOST_TYPEOF_TPL(declval_b() ? declval_T() : declval_U()) type;
124 #if defined(__GNUC__) && __GNUC__ == 3 && (__GNUC_MINOR__ == 2 || __GNUC_MINOR__ == 3)
126 void public_dummy_function_just_to_silence_warning();
131 struct common_type_2<T, T>
137 #if !defined(BOOST_NO_VARIADIC_TEMPLATES)
138 template <class T, class U>
139 struct common_type<T, U>
141 template <class T, class U>
142 struct common_type<T, U, void>
144 : type_traits_detail::common_type_2<T,U>
149 #if !defined(BOOST_NO_VARIADIC_TEMPLATES)
150 template<typename T, typename U, typename... V>
151 struct common_type<T, U, V...> {
153 typedef typename common_type<typename common_type<T, U>::type, V...>::type type;
158 #endif // BOOST_TYPE_TRAITS_COMMON_TYPE_HPP