]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/ratio/example/type_traits/detail/common_type.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / ratio / example / type_traits / detail / common_type.hpp
1 /*******************************************************************************
2 * boost/type_traits/detail/common_type.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_EX_TYPE_TRAITS_EXT_DETAIL_COMMON_TYPE_HPP
20 #define BOOST_EX_TYPE_TRAITS_EXT_DETAIL_COMMON_TYPE_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/type_traits/declval.hpp>
48
49 namespace boost_ex
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_signable_integral<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_signable_integral
83 : mpl::or_< is_integral<T>, is_enum<T> >
84 { };
85 template<>
86 struct is_signable_integral< bool >
87 : false_type
88 { };
89
90 /*******************************************************************************
91 * struct sizeof_t<N>
92 * typedef ... yes_type
93 * typedef ... no_type
94 *
95 * These types are integral players in the use of the "sizeof trick", i.e., we
96 * can distinguish overload selection by inspecting the size of the return type
97 * of the overload.
98 ******************************************************************************/
99
100 template< std::size_t N > struct sizeof_t { char _dummy[N]; };
101 typedef sizeof_t<1> yes_type;
102 typedef sizeof_t<2> no_type;
103 BOOST_MPL_ASSERT_RELATION( sizeof( yes_type ), ==, 1 );
104 BOOST_MPL_ASSERT_RELATION( sizeof( no_type ), ==, 2 );
105
106 /*******************************************************************************
107 * rvalue_test(T&) -> no_type
108 * rvalue_test(...) -> yes_type
109 *
110 * These overloads are used to determine the rvalue-ness of an expression.
111 ******************************************************************************/
112
113 template< class T > no_type rvalue_test(T&);
114 yes_type rvalue_test(...);
115
116 /*******************************************************************************
117 * struct conversion_test_overloads< Sequence >
118 *
119 * This struct has multiple overloads of the static member function apply, each
120 * one taking a single parameter of a type within the Boost.MPL sequence
121 * Sequence. Each such apply overload has a return type with sizeof equal to
122 * one plus the index of the parameter type within Sequence. Thus, we can
123 * deduce the type T of an expression as long as we can generate a finite set of
124 * candidate types containing T via these apply overloads and the "sizeof
125 * trick".
126 ******************************************************************************/
127
128 template< class First, class Last, std::size_t Index >
129 struct conversion_test_overloads_iterate
130 : conversion_test_overloads_iterate<
131 typename mpl::next< First >::type, Last, Index + 1
132 >
133 {
134 using conversion_test_overloads_iterate<
135 typename mpl::next< First >::type, Last, Index + 1
136 >::apply;
137 static sizeof_t< Index + 1 >
138 apply(typename mpl::deref< First >::type);
139 };
140
141 template< class Last, std::size_t Index >
142 struct conversion_test_overloads_iterate< Last, Last, Index >
143 { static sizeof_t< Index + 1 > apply(...); };
144
145 template< class Sequence >
146 struct conversion_test_overloads
147 : conversion_test_overloads_iterate<
148 typename mpl::begin< Sequence >::type,
149 typename mpl::end< Sequence >::type,
150 0
151 >
152 { };
153
154 /*******************************************************************************
155 * struct select< Sequence, Index >
156 *
157 * select is synonymous with mpl::at_c unless Index equals the size of the
158 * Boost.MPL Sequence, in which case this evaluates to void.
159 ******************************************************************************/
160
161 template<
162 class Sequence, int Index,
163 int N = mpl::size< Sequence >::value
164 >
165 struct select
166 : mpl::at_c< Sequence, Index >
167 { };
168 template< class Sequence, int N >
169 struct select< Sequence, N, N >
170 { typedef void type; };
171
172 /*******************************************************************************
173 * class deduce_common_type< T, U, NominalCandidates >
174 * struct nominal_candidates<T,U>
175 * struct common_type_dispatch_on_rvalueness<T,U>
176 * struct common_type_impl<T,U>
177 *
178 * These classes and structs implement the logic behind common_type, which goes
179 * roughly as follows. Let C be the type of the conditional expression
180 * declval< bool >() ? declval<T>() : declval<U>()
181 * if C is an rvalue, then:
182 * let T' and U' be T and U stripped of reference- and cv-qualifiers
183 * if T' and U' are pointer types, say, T' = V* and U' = W*, then:
184 * define the set of NominalCandidates to be
185 * { V*, W*, V'*, W'* }
186 * where V' is V with whatever cv-qualifiers are on W, and W' is W
187 * with whatever cv-qualifiers are on V
188 * else T' and U' are both "signable integral types" (integral and enum
189 * types excepting bool), then:
190 * define the set of NominalCandidates to be
191 * { unsigned(T'), unsigned(U'), signed(T'), signed(U') }
192 * where unsigned(X) is make_unsigned<X>::type and signed(X) is
193 * make_signed<X>::type
194 * else
195 * define the set of NominalCandidates to be
196 * { T', U' }
197 * else
198 * let V and W be T and U stripped of reference-qualifiers
199 * define the set of NominalCandidates to be
200 * { V&, W&, V'&, W'& }
201 * where V' is V with whatever cv-qualifiers are on W, and W' is W with
202 * whatever cv-qualifiers are on V
203 * define the set of Candidates to be equal to the set of NominalCandidates with
204 * duplicates removed, and use this set of Candidates to determine C using the
205 * conversion_test_overloads struct
206 ******************************************************************************/
207
208 template< class T, class U, class NominalCandidates >
209 class deduce_common_type
210 {
211 typedef typename mpl::copy<
212 NominalCandidates,
213 mpl::inserter<
214 mpl::vector0<>,
215 mpl::if_<
216 mpl::contains< mpl::_1, mpl::_2 >,
217 mpl::_1,
218 mpl::push_back< mpl::_1, mpl::_2 >
219 >
220 >
221 >::type candidate_types;
222 static const int best_candidate_index =
223 sizeof( conversion_test_overloads< candidate_types >::apply(
224 declval< bool >() ? declval<T>() : declval<U>()
225 ) ) - 1;
226 public:
227 typedef typename select< candidate_types, best_candidate_index >::type type;
228 };
229
230 template<
231 class T, class U,
232 class V = typename remove_cv< typename remove_reference<T>::type >::type,
233 class W = typename remove_cv< typename remove_reference<U>::type >::type,
234 bool = is_signable_integral<V>::value && is_signable_integral<W>::value
235 >
236 struct nominal_candidates;
237
238 template< class T, class U, class V, class W >
239 struct nominal_candidates< T, U, V, W, false >
240 { typedef mpl::vector2<V,W> type; };
241
242 template< class T, class U, class V, class W >
243 struct nominal_candidates< T, U, V, W, true >
244 {
245 typedef mpl::vector4<
246 typename make_unsigned<V>::type,
247 typename make_unsigned<W>::type,
248 typename make_signed<V>::type,
249 typename make_signed<W>::type
250 > type;
251 };
252
253 template< class T, class U, class V, class W >
254 struct nominal_candidates< T, U, V*, W*, false >
255 {
256 typedef mpl::vector4<
257 V*, W*,
258 typename propagate_cv<W,V>::type *,
259 typename propagate_cv<V,W>::type *
260 > type;
261 };
262
263 template<
264 class T, class U,
265 bool = sizeof( ::boost::detail_type_traits_common_type::rvalue_test(
266 declval< bool >() ? declval<T>() : declval<U>()
267 ) ) == sizeof( yes_type )
268 >
269 struct common_type_dispatch_on_rvalueness;
270
271 template< class T, class U >
272 struct common_type_dispatch_on_rvalueness< T, U, true >
273 : deduce_common_type< T, U, typename nominal_candidates<T,U>::type >
274 { };
275
276 template< class T, class U >
277 struct common_type_dispatch_on_rvalueness< T, U, false >
278 {
279 private:
280 typedef typename remove_reference<T>::type unrefed_T_type;
281 typedef typename remove_reference<U>::type unrefed_U_type;
282 public:
283 typedef typename deduce_common_type<
284 T, U,
285 mpl::vector4<
286 unrefed_T_type &,
287 unrefed_U_type &,
288 typename propagate_cv< unrefed_U_type, unrefed_T_type >::type &,
289 typename propagate_cv< unrefed_T_type, unrefed_U_type >::type &
290 >
291 >::type type;
292 };
293
294 template< class T, class U >
295 struct common_type_impl
296 : common_type_dispatch_on_rvalueness<T,U>
297 { };
298
299 template< class T > struct common_type_impl< T, void > { typedef void type; };
300 template< class T > struct common_type_impl< void, T > { typedef void type; };
301 template<> struct common_type_impl< void, void > { typedef void type; };
302 template< > struct common_type_impl< char, short> { typedef int type; };
303 template< > struct common_type_impl< short, char> { typedef int type; };
304 template< > struct common_type_impl< unsigned char, short> { typedef int type; };
305 template< > struct common_type_impl< short, unsigned char> { typedef int type; };
306 template< > struct common_type_impl< unsigned char, unsigned short> { typedef int type; };
307 template< > struct common_type_impl< unsigned short, unsigned char> { typedef int type; };
308 template< > struct common_type_impl< char, unsigned short> { typedef int type; };
309 template< > struct common_type_impl< unsigned short, char> { typedef int type; };
310
311 } // namespace detail_type_traits_common_type
312
313
314 } // namespace boost_ex
315
316 #endif // BOOST_EX_TYPE_TRAITS_EXT_DETAIL_COMMON_TYPE_HPP