]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/type_traits/is_convertible.hpp
bump version to 18.2.4-pve3
[ceph.git] / ceph / src / boost / boost / type_traits / is_convertible.hpp
1
2 // Copyright 2000 John Maddock (john@johnmaddock.co.uk)
3 // Copyright 2000 Jeremy Siek (jsiek@lsc.nd.edu)
4 // Copyright 1999, 2000 Jaakko Jarvi (jaakko.jarvi@cs.utu.fi)
5 //
6 // Use, modification and distribution are subject to the Boost Software License,
7 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
8 // http://www.boost.org/LICENSE_1_0.txt).
9 //
10 // See http://www.boost.org/libs/type_traits for most recent version including documentation.
11
12 #ifndef BOOST_TT_IS_CONVERTIBLE_HPP_INCLUDED
13 #define BOOST_TT_IS_CONVERTIBLE_HPP_INCLUDED
14
15 #include <boost/type_traits/intrinsics.hpp>
16 #include <boost/type_traits/integral_constant.hpp>
17 #include <boost/type_traits/is_complete.hpp>
18 #include <boost/type_traits/is_void.hpp>
19 #include <boost/type_traits/is_array.hpp>
20 #include <boost/static_assert.hpp>
21 #ifndef BOOST_IS_CONVERTIBLE
22 #include <boost/type_traits/detail/yes_no_type.hpp>
23 #include <boost/type_traits/detail/config.hpp>
24 #include <boost/type_traits/is_array.hpp>
25 #include <boost/type_traits/is_arithmetic.hpp>
26 #include <boost/type_traits/is_void.hpp>
27 #if !defined(BOOST_NO_IS_ABSTRACT)
28 #include <boost/type_traits/is_abstract.hpp>
29 #endif
30 #include <boost/type_traits/add_lvalue_reference.hpp>
31 #include <boost/type_traits/add_rvalue_reference.hpp>
32 #include <boost/type_traits/is_function.hpp>
33
34 #if defined(__MWERKS__)
35 #include <boost/type_traits/remove_reference.hpp>
36 #endif
37 #if !defined(BOOST_NO_SFINAE_EXPR) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
38 # include <boost/type_traits/declval.hpp>
39 #endif
40 #elif defined(BOOST_MSVC) || defined(BOOST_INTEL)
41 #include <boost/type_traits/is_function.hpp>
42 #include <boost/type_traits/is_same.hpp>
43 #endif // BOOST_IS_CONVERTIBLE
44
45 namespace boost {
46
47 #ifndef BOOST_IS_CONVERTIBLE
48
49 // is one type convertible to another?
50 //
51 // there are multiple versions of the is_convertible
52 // template, almost every compiler seems to require its
53 // own version.
54 //
55 // Thanks to Andrei Alexandrescu for the original version of the
56 // conversion detection technique!
57 //
58
59 namespace detail {
60
61 #if !defined(BOOST_NO_SFINAE_EXPR) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !(defined(BOOST_GCC) && (BOOST_GCC < 40700))
62
63 // This is a C++11 conforming version, place this first and use it wherever possible:
64
65 # define BOOST_TT_CXX11_IS_CONVERTIBLE
66
67 template <class A, class B, class C>
68 struct or_helper
69 {
70 static const bool value = (A::value || B::value || C::value);
71 };
72
73 template<typename From, typename To, bool b = or_helper<boost::is_void<From>, boost::is_function<To>, boost::is_array<To> >::value>
74 struct is_convertible_basic_impl
75 {
76 // Nothing converts to function or array, but void converts to void:
77 static const bool value = is_void<To>::value;
78 };
79
80 template<typename From, typename To>
81 class is_convertible_basic_impl<From, To, false>
82 {
83 typedef char one;
84 typedef int two;
85
86 template<typename To1>
87 static void test_aux(To1);
88
89 template<typename From1, typename To1>
90 static decltype(test_aux<To1>(boost::declval<From1>()), one()) test(int);
91
92 template<typename, typename>
93 static two test(...);
94
95 public:
96 static const bool value = sizeof(test<From, To>(0)) == 1;
97 };
98
99 #elif defined(BOOST_BORLANDC) && (BOOST_BORLANDC < 0x560)
100 //
101 // special version for Borland compilers
102 // this version breaks when used for some
103 // UDT conversions:
104 //
105 template <typename From, typename To>
106 struct is_convertible_impl
107 {
108 #pragma option push -w-8074
109 // This workaround for Borland breaks the EDG C++ frontend,
110 // so we only use it for Borland.
111 template <typename T> struct checker
112 {
113 static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(...);
114 static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(T);
115 };
116
117 static typename add_lvalue_reference<From>::type _m_from;
118 static bool const value = sizeof( checker<To>::_m_check(_m_from) )
119 == sizeof(::boost::type_traits::yes_type);
120 #pragma option pop
121 };
122
123 #elif defined(__GNUC__) || defined(BOOST_BORLANDC) && (BOOST_BORLANDC < 0x600)
124 // special version for gcc compiler + recent Borland versions
125 // note that this does not pass UDT's through (...)
126
127 struct any_conversion
128 {
129 template <typename T> any_conversion(const volatile T&);
130 template <typename T> any_conversion(const T&);
131 template <typename T> any_conversion(volatile T&);
132 template <typename T> any_conversion(T&);
133 };
134
135 template <typename T> struct checker
136 {
137 static boost::type_traits::no_type _m_check(any_conversion ...);
138 static boost::type_traits::yes_type _m_check(T, int);
139 };
140
141 template <typename From, typename To>
142 struct is_convertible_basic_impl
143 {
144 typedef typename add_lvalue_reference<From>::type lvalue_type;
145 typedef typename add_rvalue_reference<From>::type rvalue_type;
146 static lvalue_type _m_from;
147 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 6)))
148 static bool const value =
149 sizeof( boost::detail::checker<To>::_m_check(static_cast<rvalue_type>(_m_from), 0) )
150 == sizeof(::boost::type_traits::yes_type);
151 #else
152 static bool const value =
153 sizeof( boost::detail::checker<To>::_m_check(_m_from, 0) )
154 == sizeof(::boost::type_traits::yes_type);
155 #endif
156 };
157
158 #elif (defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 245) && !defined(__ICL)) \
159 || defined(__IBMCPP__) || defined(__HP_aCC)
160 //
161 // This is *almost* an ideal world implementation as it doesn't rely
162 // on undefined behaviour by passing UDT's through (...).
163 // Unfortunately it doesn't quite pass all the tests for most compilers (sigh...)
164 // Enable this for your compiler if is_convertible_test.cpp will compile it...
165 //
166 // Note we do not enable this for VC7.1, because even though it passes all the
167 // type_traits tests it is known to cause problems when instantiation occurs
168 // deep within the instantiation tree :-(
169 //
170 struct any_conversion
171 {
172 template <typename T> any_conversion(const volatile T&);
173 template <typename T> any_conversion(const T&);
174 template <typename T> any_conversion(volatile T&);
175 // we need this constructor to catch references to functions
176 // (which can not be cv-qualified):
177 template <typename T> any_conversion(T&);
178 };
179
180 template <typename From, typename To>
181 struct is_convertible_basic_impl
182 {
183 static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(any_conversion ...);
184 static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(To, int);
185 typedef typename add_lvalue_reference<From>::type lvalue_type;
186 typedef typename add_rvalue_reference<From>::type rvalue_type;
187 static lvalue_type _m_from;
188
189 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
190 BOOST_STATIC_CONSTANT(bool, value =
191 sizeof( _m_check(static_cast<rvalue_type>(_m_from), 0) ) == sizeof(::boost::type_traits::yes_type)
192 );
193 #else
194 BOOST_STATIC_CONSTANT(bool, value =
195 sizeof( _m_check(_m_from, 0) ) == sizeof(::boost::type_traits::yes_type)
196 );
197 #endif
198 };
199
200 #elif defined(__DMC__)
201
202 struct any_conversion
203 {
204 template <typename T> any_conversion(const volatile T&);
205 template <typename T> any_conversion(const T&);
206 template <typename T> any_conversion(volatile T&);
207 // we need this constructor to catch references to functions
208 // (which can not be cv-qualified):
209 template <typename T> any_conversion(T&);
210 };
211
212 template <typename From, typename To>
213 struct is_convertible_basic_impl
214 {
215 // Using '...' doesn't always work on Digital Mars. This version seems to.
216 template <class T>
217 static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(any_conversion, float, T);
218 static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(To, int, int);
219 typedef typename add_lvalue_reference<From>::type lvalue_type;
220 typedef typename add_rvalue_reference<From>::type rvalue_type;
221 static lvalue_type _m_from;
222
223 // Static constants sometime cause the conversion of _m_from to To to be
224 // called. This doesn't happen with an enum.
225 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
226 enum { value =
227 sizeof( _m_check(static_cast<rvalue_type>(_m_from), 0, 0) ) == sizeof(::boost::type_traits::yes_type)
228 };
229 #else
230 enum { value =
231 sizeof( _m_check(_m_from, 0, 0) ) == sizeof(::boost::type_traits::yes_type)
232 };
233 #endif
234 };
235
236 #elif defined(__MWERKS__)
237 //
238 // CW works with the technique implemented above for EDG, except when From
239 // is a function type (or a reference to such a type), in which case
240 // any_conversion won't be accepted as a valid conversion. We detect this
241 // exceptional situation and channel it through an alternative algorithm.
242 //
243
244 template <typename From, typename To,bool FromIsFunctionRef>
245 struct is_convertible_basic_impl_aux;
246
247 struct any_conversion
248 {
249 template <typename T> any_conversion(const volatile T&);
250 template <typename T> any_conversion(const T&);
251 template <typename T> any_conversion(volatile T&);
252 template <typename T> any_conversion(T&);
253 };
254
255 template <typename From, typename To>
256 struct is_convertible_basic_impl_aux<From,To,false /*FromIsFunctionRef*/>
257 {
258 static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(any_conversion ...);
259 static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(To, int);
260 typedef typename add_lvalue_reference<From>::type lvalue_type;
261 typedef typename add_rvalue_reference<From>::type rvalue_type;
262 static lvalue_type _m_from;
263
264 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
265 BOOST_STATIC_CONSTANT(bool, value =
266 sizeof( _m_check(static_cast<rvalue_type>(_m_from), 0) ) == sizeof(::boost::type_traits::yes_type)
267 );
268 #else
269 BOOST_STATIC_CONSTANT(bool, value =
270 sizeof( _m_check(_m_from, 0) ) == sizeof(::boost::type_traits::yes_type)
271 );
272 #endif
273 };
274
275 template <typename From, typename To>
276 struct is_convertible_basic_impl_aux<From,To,true /*FromIsFunctionRef*/>
277 {
278 static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(...);
279 static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(To);
280 typedef typename add_lvalue_reference<From>::type lvalue_type;
281 typedef typename add_rvalue_reference<From>::type rvalue_type;
282 static lvalue_type _m_from;
283 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
284 BOOST_STATIC_CONSTANT(bool, value =
285 sizeof( _m_check(static_cast<rvalue_type>(_m_from)) ) == sizeof(::boost::type_traits::yes_type)
286 );
287 #else
288 BOOST_STATIC_CONSTANT(bool, value =
289 sizeof( _m_check(_m_from) ) == sizeof(::boost::type_traits::yes_type)
290 );
291 #endif
292 };
293
294 template <typename From, typename To>
295 struct is_convertible_basic_impl:
296 is_convertible_basic_impl_aux<
297 From,To,
298 ::boost::is_function<typename ::boost::remove_reference<From>::type>::value
299 >
300 {};
301
302 #else
303 //
304 // This version seems to work pretty well for a wide spectrum of compilers,
305 // however it does rely on undefined behaviour by passing UDT's through (...).
306 //
307
308 //Workaround for old compilers like MSVC 7.1 to avoid
309 //forming a reference to an array of unknown bound
310 template <typename From>
311 struct is_convertible_basic_impl_add_lvalue_reference
312 : add_lvalue_reference<From>
313 {};
314
315 template <typename From>
316 struct is_convertible_basic_impl_add_lvalue_reference<From[]>
317 {
318 typedef From type [];
319 };
320
321 template <typename From, typename To>
322 struct is_convertible_basic_impl
323 {
324 static ::boost::type_traits::no_type BOOST_TT_DECL _m_check(...);
325 static ::boost::type_traits::yes_type BOOST_TT_DECL _m_check(To);
326 typedef typename is_convertible_basic_impl_add_lvalue_reference<From>::type lvalue_type;
327 static lvalue_type _m_from;
328 #ifdef BOOST_MSVC
329 #pragma warning(push)
330 #pragma warning(disable:4244)
331 #if BOOST_WORKAROUND(BOOST_MSVC_FULL_VER, >= 140050000)
332 #pragma warning(disable:6334)
333 #endif
334 #endif
335 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
336 typedef typename add_rvalue_reference<From>::type rvalue_type;
337 BOOST_STATIC_CONSTANT(bool, value =
338 sizeof( _m_check(static_cast<rvalue_type>(_m_from)) ) == sizeof(::boost::type_traits::yes_type)
339 );
340 #else
341 BOOST_STATIC_CONSTANT(bool, value =
342 sizeof( _m_check(_m_from) ) == sizeof(::boost::type_traits::yes_type)
343 );
344 #endif
345 #ifdef BOOST_MSVC
346 #pragma warning(pop)
347 #endif
348 };
349
350 #endif // is_convertible_impl
351
352 #if defined(__DMC__)
353 // As before, a static constant sometimes causes errors on Digital Mars.
354 template <typename From, typename To>
355 struct is_convertible_impl
356 {
357 enum {
358 value = ( ::boost::detail::is_convertible_basic_impl<From,To>::value && ! ::boost::is_array<To>::value && ! ::boost::is_function<To>::value)
359 };
360 };
361 #elif !defined(BOOST_BORLANDC) || BOOST_BORLANDC > 0x551
362 template <typename From, typename To>
363 struct is_convertible_impl
364 {
365 BOOST_STATIC_CONSTANT(bool, value = ( ::boost::detail::is_convertible_basic_impl<From, To>::value && !::boost::is_array<To>::value && !::boost::is_function<To>::value));
366 };
367 #endif
368
369 template <bool trivial1, bool trivial2, bool abstract_target>
370 struct is_convertible_impl_select
371 {
372 template <class From, class To>
373 struct rebind
374 {
375 typedef is_convertible_impl<From, To> type;
376 };
377 };
378
379 template <>
380 struct is_convertible_impl_select<true, true, false>
381 {
382 template <class From, class To>
383 struct rebind
384 {
385 typedef true_type type;
386 };
387 };
388
389 template <>
390 struct is_convertible_impl_select<false, false, true>
391 {
392 template <class From, class To>
393 struct rebind
394 {
395 typedef false_type type;
396 };
397 };
398
399 template <>
400 struct is_convertible_impl_select<true, false, true>
401 {
402 template <class From, class To>
403 struct rebind
404 {
405 typedef false_type type;
406 };
407 };
408
409 template <typename From, typename To>
410 struct is_convertible_impl_dispatch_base
411 {
412 #if !BOOST_WORKAROUND(__HP_aCC, < 60700)
413 typedef is_convertible_impl_select<
414 ::boost::is_arithmetic<From>::value,
415 ::boost::is_arithmetic<To>::value,
416 #if !defined(BOOST_NO_IS_ABSTRACT) && !defined(BOOST_TT_CXX11_IS_CONVERTIBLE)
417 // We need to filter out abstract types, only if we don't have a strictly conforming C++11 version:
418 ::boost::is_abstract<To>::value
419 #else
420 false
421 #endif
422 > selector;
423 #else
424 typedef is_convertible_impl_select<false, false, false> selector;
425 #endif
426 typedef typename selector::template rebind<From, To> isc_binder;
427 typedef typename isc_binder::type type;
428 };
429
430 template <typename From, typename To>
431 struct is_convertible_impl_dispatch
432 : public is_convertible_impl_dispatch_base<From, To>::type
433 {};
434
435 //
436 // Now add the full and partial specialisations
437 // for void types, these are common to all the
438 // implementation above:
439 //
440 #ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
441
442 template <> struct is_convertible_impl_dispatch<void, void> : public true_type{};
443 template <> struct is_convertible_impl_dispatch<void, void const> : public true_type{};
444 template <> struct is_convertible_impl_dispatch<void, void const volatile> : public true_type{};
445 template <> struct is_convertible_impl_dispatch<void, void volatile> : public true_type{};
446
447 template <> struct is_convertible_impl_dispatch<void const, void> : public true_type{};
448 template <> struct is_convertible_impl_dispatch<void const, void const> : public true_type{};
449 template <> struct is_convertible_impl_dispatch<void const, void const volatile> : public true_type{};
450 template <> struct is_convertible_impl_dispatch<void const, void volatile> : public true_type{};
451
452 template <> struct is_convertible_impl_dispatch<void const volatile, void> : public true_type{};
453 template <> struct is_convertible_impl_dispatch<void const volatile, void const> : public true_type{};
454 template <> struct is_convertible_impl_dispatch<void const volatile, void const volatile> : public true_type{};
455 template <> struct is_convertible_impl_dispatch<void const volatile, void volatile> : public true_type{};
456
457 template <> struct is_convertible_impl_dispatch<void volatile, void> : public true_type{};
458 template <> struct is_convertible_impl_dispatch<void volatile, void const> : public true_type{};
459 template <> struct is_convertible_impl_dispatch<void volatile, void const volatile> : public true_type{};
460 template <> struct is_convertible_impl_dispatch<void volatile, void volatile> : public true_type{};
461
462 #else
463 template <> struct is_convertible_impl_dispatch<void, void> : public true_type{};
464 #endif // BOOST_NO_CV_VOID_SPECIALIZATIONS
465
466 template <class To> struct is_convertible_impl_dispatch<void, To> : public false_type{};
467 template <class From> struct is_convertible_impl_dispatch<From, void> : public false_type{};
468
469 #ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
470 template <class To> struct is_convertible_impl_dispatch<void const, To> : public false_type{};
471 template <class From> struct is_convertible_impl_dispatch<From, void const> : public false_type{};
472 template <class To> struct is_convertible_impl_dispatch<void const volatile, To> : public false_type{};
473 template <class From> struct is_convertible_impl_dispatch<From, void const volatile> : public false_type{};
474 template <class To> struct is_convertible_impl_dispatch<void volatile, To> : public false_type{};
475 template <class From> struct is_convertible_impl_dispatch<From, void volatile> : public false_type{};
476 #endif
477
478 } // namespace detail
479
480 template <class From, class To>
481 struct is_convertible : public integral_constant<bool, ::boost::detail::is_convertible_impl_dispatch<From, To>::value>
482 {
483 BOOST_STATIC_ASSERT_MSG(boost::is_complete<To>::value || boost::is_void<To>::value || boost::is_array<To>::value, "Destination argument type to is_convertible must be a complete type");
484 BOOST_STATIC_ASSERT_MSG(boost::is_complete<From>::value || boost::is_void<From>::value || boost::is_array<From>::value, "From argument type to is_convertible must be a complete type");
485 };
486
487 #else
488
489 template <class From, class To>
490 struct is_convertible : public integral_constant<bool, BOOST_IS_CONVERTIBLE(From, To)>
491 {
492 #if defined(BOOST_MSVC)
493 BOOST_STATIC_ASSERT_MSG(boost::is_complete<From>::value || boost::is_void<From>::value || boost::is_array<From>::value || boost::is_reference<From>::value, "From argument type to is_convertible must be a complete type");
494 #endif
495 #if defined(__clang__)
496 // clang's intrinsic doesn't assert on incomplete types:
497 BOOST_STATIC_ASSERT_MSG(boost::is_complete<To>::value || boost::is_void<To>::value || boost::is_array<To>::value, "Destination argument type to is_convertible must be a complete type");
498 BOOST_STATIC_ASSERT_MSG(boost::is_complete<From>::value || boost::is_void<From>::value || boost::is_array<From>::value, "From argument type to is_convertible must be a complete type");
499 #endif
500 };
501
502 #endif
503
504 } // namespace boost
505
506 #endif // BOOST_TT_IS_CONVERTIBLE_HPP_INCLUDED