]> git.donarmstrong.com Git - rsem.git/blob - boost/type_traits/detail/common_type_imp.hpp
84de8b4125e255f71edbedd497d30dd1df204d30
[rsem.git] / boost / type_traits / detail / common_type_imp.hpp
1 /*******************************************************************************
2  * boost/type_traits/detail/common_type_imp.hpp
3  *
4  * Copyright 2010, Jeffrey Hellrung.
5  * Distributed under the Boost Software License, Version 1.0.  (See accompanying
6  * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7  *
8  * struct boost::common_type<T,U>
9  *
10  * common_type<T,U>::type is the type of the expression
11  *     b() ? x() : y()
12  * where b() returns a bool, x() has return type T, and y() has return type U.
13  * See
14  *     http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2661.htm#common_type
15  *
16  * Note that this evaluates to void if one or both of T and U is void.
17  ******************************************************************************/
18
19 #ifndef BOOST_TYPE_TRAITS_DETAIL_COMMON_TYPE_IMP_HPP
20 #define BOOST_TYPE_TRAITS_DETAIL_COMMON_TYPE_IMP_HPP
21
22 #include <cstddef>
23
24 #include <boost/mpl/assert.hpp>
25 #include <boost/mpl/at.hpp>
26 #include <boost/mpl/begin_end.hpp>
27 #include <boost/mpl/contains.hpp>
28 #include <boost/mpl/copy.hpp>
29 #include <boost/mpl/deref.hpp>
30 #include <boost/mpl/eval_if.hpp>
31 #include <boost/mpl/if.hpp>
32 #include <boost/mpl/inserter.hpp>
33 #include <boost/mpl/next.hpp>
34 #include <boost/mpl/or.hpp>
35 #include <boost/mpl/placeholders.hpp>
36 #include <boost/mpl/push_back.hpp>
37 #include <boost/mpl/size.hpp>
38 #include <boost/mpl/vector/vector0.hpp>
39 #include <boost/mpl/vector/vector10.hpp>
40 #include <boost/type_traits/integral_constant.hpp>
41 #include <boost/type_traits/is_enum.hpp>
42 #include <boost/type_traits/is_integral.hpp>
43 #include <boost/type_traits/make_signed.hpp>
44 #include <boost/type_traits/make_unsigned.hpp>
45 #include <boost/type_traits/remove_cv.hpp>
46 #include <boost/type_traits/remove_reference.hpp>
47 #include <boost/utility/declval.hpp>
48
49 namespace boost
50 {
51
52 namespace detail_type_traits_common_type
53 {
54
55 /*******************************************************************************
56  * struct propagate_cv< From, To >
57  *
58  * This metafunction propagates cv-qualifiers on type From to type To.
59  ******************************************************************************/
60
61 template< class From, class To >
62 struct propagate_cv
63 { typedef To type; };
64 template< class From, class To >
65 struct propagate_cv< const From, To >
66 { typedef To const type; };
67 template< class From, class To >
68 struct propagate_cv< volatile From, To >
69 { typedef To volatile type; };
70 template< class From, class To >
71 struct propagate_cv< const volatile From, To >
72 { typedef To const volatile type; };
73
74 /*******************************************************************************
75  * struct is_integral_or_enum<T>
76  *
77  * This metafunction determines if T is an integral type which can be made
78  * signed or unsigned.
79  ******************************************************************************/
80
81 template< class T >
82 struct is_integral_or_enum
83     : public mpl::or_< is_integral<T>, is_enum<T> >
84 { };
85 template<>
86 struct is_integral_or_enum< bool >
87     : public false_type
88 { };
89
90 /*******************************************************************************
91  * struct make_unsigned_soft<T>
92  * struct make_signed_soft<T>
93  *
94  * These metafunction are identical to make_unsigned and make_signed,
95  * respectively, except for special-casing bool.
96  ******************************************************************************/
97
98 template< class T >
99 struct make_unsigned_soft
100     : public make_unsigned<T>
101 { };
102 template<>
103 struct make_unsigned_soft< bool >
104 { typedef bool type; };
105
106 template< class T >
107 struct make_signed_soft
108     : public make_signed<T>
109 { };
110 template<>
111 struct make_signed_soft< bool >
112 { typedef bool type; };
113
114 /*******************************************************************************
115  * struct sizeof_t<N>
116  * typedef ... yes_type
117  * typedef ... no_type
118  *
119  * These types are integral players in the use of the "sizeof trick", i.e., we
120  * can distinguish overload selection by inspecting the size of the return type
121  * of the overload.
122  ******************************************************************************/
123
124 template< std::size_t N > struct sizeof_t { char _dummy[N]; };
125 typedef sizeof_t<1> yes_type;
126 typedef sizeof_t<2> no_type;
127 BOOST_MPL_ASSERT_RELATION( sizeof( yes_type ), ==, 1 );
128 BOOST_MPL_ASSERT_RELATION( sizeof( no_type ), ==, 2 );
129
130 /*******************************************************************************
131  * rvalue_test(T&) -> no_type
132  * rvalue_test(...) -> yes_type
133  *
134  * These overloads are used to determine the rvalue-ness of an expression.
135  ******************************************************************************/
136
137 template< class T > no_type rvalue_test(T&);
138 yes_type rvalue_test(...);
139
140 /*******************************************************************************
141  * struct conversion_test_overloads< Sequence >
142  *
143  * This struct has multiple overloads of the static member function apply, each
144  * one taking a single parameter of a type within the Boost.MPL sequence
145  * Sequence.  Each such apply overload has a return type with sizeof equal to
146  * one plus the index of the parameter type within Sequence.  Thus, we can
147  * deduce the type T of an expression as long as we can generate a finite set of
148  * candidate types containing T via these apply overloads and the "sizeof
149  * trick".
150  ******************************************************************************/
151
152 template< class First, class Last, std::size_t Index >
153 struct conversion_test_overloads_iterate
154     : public conversion_test_overloads_iterate<
155           typename mpl::next< First >::type, Last, Index + 1
156       >
157 {
158     using conversion_test_overloads_iterate<
159         typename mpl::next< First >::type, Last, Index + 1
160     >::apply;
161     static sizeof_t< Index + 1 >
162     apply(typename mpl::deref< First >::type);
163 };
164
165 template< class Last, std::size_t Index >
166 struct conversion_test_overloads_iterate< Last, Last, Index >
167 { static sizeof_t< Index + 1 > apply(...); };
168
169 template< class Sequence >
170 struct conversion_test_overloads
171     : public conversion_test_overloads_iterate<
172           typename mpl::begin< Sequence >::type,
173           typename mpl::end< Sequence >::type,
174           0
175       >
176 { };
177
178 /*******************************************************************************
179  * struct select< Sequence, Index >
180  *
181  * select is synonymous with mpl::at_c unless Index equals the size of the
182  * Boost.MPL Sequence, in which case this evaluates to void.
183  ******************************************************************************/
184
185 template<
186     class Sequence, int Index,
187     int N = mpl::size< Sequence >::value
188 >
189 struct select
190     : public mpl::at_c< Sequence, Index >
191 { };
192 template< class Sequence, int N >
193 struct select< Sequence, N, N >
194 { typedef void type; };
195
196 /*******************************************************************************
197  * class deduce_common_type< T, U, NominalCandidates >
198  * struct nominal_candidates<T,U>
199  * struct common_type_dispatch_on_rvalueness<T,U>
200  * struct common_type_impl<T,U>
201  *
202  * These classes and structs implement the logic behind common_type, which goes
203  * roughly as follows.  Let C be the type of the conditional expression
204  *     declval< bool >() ? declval<T>() : declval<U>()
205  * if C is an rvalue, then:
206  *     let T' and U' be T and U stripped of reference- and cv-qualifiers
207  *     if T' and U' are pointer types, say, T' = V* and U' = W*, then:
208  *         define the set of NominalCandidates to be
209  *             { V*, W*, V'*, W'* }
210  *           where V' is V with whatever cv-qualifiers are on W, and W' is W
211  *           with whatever cv-qualifiers are on V
212  *     else if T' and U' are both integral or enum types, then:
213  *         define the set of NominalCandidates to be
214  *             {
215  *                 unsigned_soft(T'),
216  *                 unsigned_soft(U'),
217  *                 signed_soft(T'),
218  *                 signed_soft(U'),
219  *                 T',
220  *                 U',
221  *                 unsigned int,
222  *                 int
223  *             }
224  *           where unsigned_soft(X) is make_unsigned_soft<X>::type and
225  *           signed_soft(X) is make_signed_soft<X>::type (these are all
226  *           generally necessary to cover the various integral promotion cases)
227  *     else
228  *         define the set of NominalCandidates to be
229  *             { T', U' }
230  * else
231  *     let V and W be T and U stripped of reference-qualifiers
232  *     define the set of NominalCandidates to be
233  *         { V&, W&, V'&, W'& }
234  *     where V' is V with whatever cv-qualifiers are on W, and W' is W with
235  *       whatever cv-qualifiers are on V
236  * define the set of Candidates to be equal to the set of NominalCandidates with
237  * duplicates removed, and use this set of Candidates to determine C using the
238  * conversion_test_overloads struct
239  ******************************************************************************/
240
241 template< class T, class U, class NominalCandidates >
242 class deduce_common_type
243 {
244     typedef typename mpl::copy<
245         NominalCandidates,
246         mpl::inserter<
247             mpl::vector0<>,
248             mpl::if_<
249                 mpl::contains< mpl::_1, mpl::_2 >,
250                 mpl::_1,
251                 mpl::push_back< mpl::_1, mpl::_2 >
252             >
253         >
254     >::type candidate_types;
255     static const int best_candidate_index =
256         sizeof( conversion_test_overloads< candidate_types >::apply(
257             declval< bool >() ? declval<T>() : declval<U>()
258         ) ) - 1;
259 public:
260     typedef typename select< candidate_types, best_candidate_index >::type type;
261 };
262
263 template<
264     class T, class U,
265     class V = typename remove_cv< typename remove_reference<T>::type >::type,
266     class W = typename remove_cv< typename remove_reference<U>::type >::type,
267     bool = is_integral_or_enum<V>::value && is_integral_or_enum<W>::value
268 >
269 struct nominal_candidates
270 { typedef mpl::vector2<V,W> type; };
271
272 template< class T, class U, class V, class W >
273 struct nominal_candidates< T, U, V, W, true >
274 {
275     typedef boost::mpl::vector8<
276         typename make_unsigned_soft<V>::type,
277         typename make_unsigned_soft<W>::type,
278         typename make_signed_soft<V>::type,
279         typename make_signed_soft<W>::type,
280         V, W, unsigned int, int
281     > type;
282 };
283
284 template< class T, class U, class V, class W >
285 struct nominal_candidates< T, U, V*, W*, false >
286 {
287     typedef mpl::vector4<
288         V*, W*,
289         typename propagate_cv<W,V>::type *,
290         typename propagate_cv<V,W>::type *
291     > type;
292 };
293
294 template<class T, class U, bool b>
295 struct common_type_dispatch_on_rvalueness
296     : public deduce_common_type< T, U, typename nominal_candidates<T,U>::type >
297 { };
298
299 template< class T, class U >
300 struct common_type_dispatch_on_rvalueness< T, U, false >
301 {
302 private:
303     typedef typename remove_reference<T>::type unrefed_T_type;
304     typedef typename remove_reference<U>::type unrefed_U_type;
305 public:
306     typedef typename deduce_common_type<
307         T, U,
308         mpl::vector4<
309             unrefed_T_type &,
310             unrefed_U_type &,
311             typename propagate_cv< unrefed_U_type, unrefed_T_type >::type &,
312             typename propagate_cv< unrefed_T_type, unrefed_U_type >::type &
313         >
314     >::type type;
315 };
316
317 template< class T, class U >
318 struct common_type_impl
319     : public common_type_dispatch_on_rvalueness<T,U, sizeof( ::boost::detail_type_traits_common_type::rvalue_test(
320         declval< bool >() ? declval<T>() : declval<U>() ) ) == sizeof( yes_type ) >
321 { };
322
323 template< class T > struct common_type_impl< T, void > { typedef void type; };
324 template< class T > struct common_type_impl< void, T > { typedef void type; };
325 template<> struct common_type_impl< void, void > { typedef void type; };
326
327 } // namespace detail_type_traits_common_type
328
329
330 } // namespace boost
331
332 #endif // BOOST_TYPE_TRAITS_DETAIL_COMMON_TYPE_HPP
333