blob: e34579d1b9ea1e19ad54777ad6fee841f8facc8f [file] [log] [blame]
Jeff Thompsonf7d49942013-08-01 16:47:40 -07001
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
Jeff Thompson2277ce52013-08-01 17:34:11 -070015#include <ndnboost/type_traits/intrinsics.hpp>
Jeff Thompsonf7d49942013-08-01 16:47:40 -070016#ifndef BOOST_IS_CONVERTIBLE
Jeff Thompson2277ce52013-08-01 17:34:11 -070017#include <ndnboost/type_traits/detail/yes_no_type.hpp>
18#include <ndnboost/type_traits/config.hpp>
19#include <ndnboost/type_traits/is_array.hpp>
20#include <ndnboost/type_traits/ice.hpp>
21#include <ndnboost/type_traits/is_arithmetic.hpp>
22#include <ndnboost/type_traits/is_void.hpp>
Jeff Thompsonf7d49942013-08-01 16:47:40 -070023#ifndef BOOST_NO_IS_ABSTRACT
Jeff Thompson2277ce52013-08-01 17:34:11 -070024#include <ndnboost/type_traits/is_abstract.hpp>
Jeff Thompsonf7d49942013-08-01 16:47:40 -070025#endif
Jeff Thompson2277ce52013-08-01 17:34:11 -070026#include <ndnboost/type_traits/add_lvalue_reference.hpp>
27#include <ndnboost/type_traits/add_rvalue_reference.hpp>
28#include <ndnboost/type_traits/is_function.hpp>
Jeff Thompsonf7d49942013-08-01 16:47:40 -070029
30#if defined(__MWERKS__)
Jeff Thompson2277ce52013-08-01 17:34:11 -070031#include <ndnboost/type_traits/remove_reference.hpp>
Jeff Thompsonf7d49942013-08-01 16:47:40 -070032#endif
33
34#endif // BOOST_IS_CONVERTIBLE
35
36// should be always the last #include directive
Jeff Thompson2277ce52013-08-01 17:34:11 -070037#include <ndnboost/type_traits/detail/bool_trait_def.hpp>
Jeff Thompsonf7d49942013-08-01 16:47:40 -070038
39namespace ndnboost {
40
41#ifndef BOOST_IS_CONVERTIBLE
42
43// is one type convertible to another?
44//
45// there are multiple versions of the is_convertible
46// template, almost every compiler seems to require its
47// own version.
48//
49// Thanks to Andrei Alexandrescu for the original version of the
50// conversion detection technique!
51//
52
53namespace detail {
54
55// MS specific version:
56
57#if defined(BOOST_MSVC) && (BOOST_MSVC <= 1300)
58
59// This workaround is necessary to handle when From is void
60// which is normally taken care of by the partial specialization
61// of the is_convertible typename.
62using ::ndnboost::type_traits::yes_type;
63using ::ndnboost::type_traits::no_type;
64
65template< typename From >
66struct does_conversion_exist
67{
68 template< typename To > struct result_
69 {
70 static no_type BOOST_TT_DECL _m_check(...);
71 static yes_type BOOST_TT_DECL _m_check(To);
72 static typename add_lvalue_reference<From>::type _m_from;
73 enum { value = sizeof( _m_check(_m_from) ) == sizeof(yes_type) };
74 };
75};
76
77template<>
78struct does_conversion_exist<void>
79{
80 template< typename To > struct result_
81 {
82 enum { value = ::ndnboost::is_void<To>::value };
83 };
84};
85
86template <typename From, typename To>
87struct is_convertible_basic_impl
88 : public does_conversion_exist<From>::template result_<To>
89{
90};
91
92#elif defined(__BORLANDC__) && (__BORLANDC__ < 0x560)
93//
94// special version for Borland compilers
95// this version breaks when used for some
96// UDT conversions:
97//
98template <typename From, typename To>
99struct is_convertible_impl
100{
101#pragma option push -w-8074
102 // This workaround for Borland breaks the EDG C++ frontend,
103 // so we only use it for Borland.
104 template <typename T> struct checker
105 {
106 static ::ndnboost::type_traits::no_type BOOST_TT_DECL _m_check(...);
107 static ::ndnboost::type_traits::yes_type BOOST_TT_DECL _m_check(T);
108 };
109
110 static typename add_lvalue_reference<From>::type _m_from;
111 static bool const value = sizeof( checker<To>::_m_check(_m_from) )
112 == sizeof(::ndnboost::type_traits::yes_type);
113#pragma option pop
114};
115
116#elif defined(__GNUC__) || defined(__BORLANDC__) && (__BORLANDC__ < 0x600)
117// special version for gcc compiler + recent Borland versions
118// note that this does not pass UDT's through (...)
119
120struct any_conversion
121{
122 template <typename T> any_conversion(const volatile T&);
123 template <typename T> any_conversion(const T&);
124 template <typename T> any_conversion(volatile T&);
125 template <typename T> any_conversion(T&);
126};
127
128template <typename T> struct checker
129{
130 static ndnboost::type_traits::no_type _m_check(any_conversion ...);
131 static ndnboost::type_traits::yes_type _m_check(T, int);
132};
133
134template <typename From, typename To>
135struct is_convertible_basic_impl
136{
137 typedef typename add_lvalue_reference<From>::type lvalue_type;
138 typedef typename add_rvalue_reference<From>::type rvalue_type;
139 static lvalue_type _m_from;
140#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 6)))
141 static bool const value =
142 sizeof( ndnboost::detail::checker<To>::_m_check(static_cast<rvalue_type>(_m_from), 0) )
143 == sizeof(::ndnboost::type_traits::yes_type);
144#else
145 static bool const value =
146 sizeof( ndnboost::detail::checker<To>::_m_check(_m_from, 0) )
147 == sizeof(::ndnboost::type_traits::yes_type);
148#endif
149};
150
151#elif (defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 245) && !defined(__ICL)) \
152 || defined(__IBMCPP__) || defined(__HP_aCC)
153//
154// This is *almost* an ideal world implementation as it doesn't rely
155// on undefined behaviour by passing UDT's through (...).
156// Unfortunately it doesn't quite pass all the tests for most compilers (sigh...)
157// Enable this for your compiler if is_convertible_test.cpp will compile it...
158//
159// Note we do not enable this for VC7.1, because even though it passes all the
160// type_traits tests it is known to cause problems when instantiation occurs
161// deep within the instantiation tree :-(
162//
163struct any_conversion
164{
165 template <typename T> any_conversion(const volatile T&);
166 template <typename T> any_conversion(const T&);
167 template <typename T> any_conversion(volatile T&);
168 // we need this constructor to catch references to functions
169 // (which can not be cv-qualified):
170 template <typename T> any_conversion(T&);
171};
172
173template <typename From, typename To>
174struct is_convertible_basic_impl
175{
176 static ::ndnboost::type_traits::no_type BOOST_TT_DECL _m_check(any_conversion ...);
177 static ::ndnboost::type_traits::yes_type BOOST_TT_DECL _m_check(To, int);
178 typedef typename add_lvalue_reference<From>::type lvalue_type;
179 typedef typename add_rvalue_reference<From>::type rvalue_type;
180 static lvalue_type _m_from;
181
182#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
183 BOOST_STATIC_CONSTANT(bool, value =
184 sizeof( _m_check(static_cast<rvalue_type>(_m_from), 0) ) == sizeof(::ndnboost::type_traits::yes_type)
185 );
186#else
187 BOOST_STATIC_CONSTANT(bool, value =
188 sizeof( _m_check(_m_from, 0) ) == sizeof(::ndnboost::type_traits::yes_type)
189 );
190#endif
191};
192
193#elif defined(__DMC__)
194
195struct any_conversion
196{
197 template <typename T> any_conversion(const volatile T&);
198 template <typename T> any_conversion(const T&);
199 template <typename T> any_conversion(volatile T&);
200 // we need this constructor to catch references to functions
201 // (which can not be cv-qualified):
202 template <typename T> any_conversion(T&);
203};
204
205template <typename From, typename To>
206struct is_convertible_basic_impl
207{
208 // Using '...' doesn't always work on Digital Mars. This version seems to.
209 template <class T>
210 static ::ndnboost::type_traits::no_type BOOST_TT_DECL _m_check(any_conversion, float, T);
211 static ::ndnboost::type_traits::yes_type BOOST_TT_DECL _m_check(To, int, int);
212 typedef typename add_lvalue_reference<From>::type lvalue_type;
213 typedef typename add_rvalue_reference<From>::type rvalue_type;
214 static lvalue_type _m_from;
215
216 // Static constants sometime cause the conversion of _m_from to To to be
217 // called. This doesn't happen with an enum.
218#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
219 enum { value =
220 sizeof( _m_check(static_cast<rvalue_type>(_m_from), 0, 0) ) == sizeof(::ndnboost::type_traits::yes_type)
221 };
222#else
223 enum { value =
224 sizeof( _m_check(_m_from, 0, 0) ) == sizeof(::ndnboost::type_traits::yes_type)
225 };
226#endif
227};
228
229#elif defined(__MWERKS__)
230//
231// CW works with the technique implemented above for EDG, except when From
232// is a function type (or a reference to such a type), in which case
233// any_conversion won't be accepted as a valid conversion. We detect this
234// exceptional situation and channel it through an alternative algorithm.
235//
236
237template <typename From, typename To,bool FromIsFunctionRef>
238struct is_convertible_basic_impl_aux;
239
240struct any_conversion
241{
242 template <typename T> any_conversion(const volatile T&);
243 template <typename T> any_conversion(const T&);
244 template <typename T> any_conversion(volatile T&);
245 template <typename T> any_conversion(T&);
246};
247
248template <typename From, typename To>
249struct is_convertible_basic_impl_aux<From,To,false /*FromIsFunctionRef*/>
250{
251 static ::ndnboost::type_traits::no_type BOOST_TT_DECL _m_check(any_conversion ...);
252 static ::ndnboost::type_traits::yes_type BOOST_TT_DECL _m_check(To, int);
253 typedef typename add_lvalue_reference<From>::type lvalue_type;
254 typedef typename add_rvalue_reference<From>::type rvalue_type;
255 static lvalue_type _m_from;
256
257#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
258 BOOST_STATIC_CONSTANT(bool, value =
259 sizeof( _m_check(static_cast<rvalue_type>(_m_from), 0) ) == sizeof(::ndnboost::type_traits::yes_type)
260 );
261#else
262 BOOST_STATIC_CONSTANT(bool, value =
263 sizeof( _m_check(_m_from, 0) ) == sizeof(::ndnboost::type_traits::yes_type)
264 );
265#endif
266};
267
268template <typename From, typename To>
269struct is_convertible_basic_impl_aux<From,To,true /*FromIsFunctionRef*/>
270{
271 static ::ndnboost::type_traits::no_type BOOST_TT_DECL _m_check(...);
272 static ::ndnboost::type_traits::yes_type BOOST_TT_DECL _m_check(To);
273 typedef typename add_lvalue_reference<From>::type lvalue_type;
274 typedef typename add_rvalue_reference<From>::type rvalue_type;
275 static lvalue_type _m_from;
276#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
277 BOOST_STATIC_CONSTANT(bool, value =
278 sizeof( _m_check(static_cast<rvalue_type>(_m_from)) ) == sizeof(::ndnboost::type_traits::yes_type)
279 );
280#else
281 BOOST_STATIC_CONSTANT(bool, value =
282 sizeof( _m_check(_m_from) ) == sizeof(::ndnboost::type_traits::yes_type)
283 );
284#endif
285};
286
287template <typename From, typename To>
288struct is_convertible_basic_impl:
289 is_convertible_basic_impl_aux<
290 From,To,
291 ::ndnboost::is_function<typename ::ndnboost::remove_reference<From>::type>::value
292 >
293{};
294
295#else
296//
297// This version seems to work pretty well for a wide spectrum of compilers,
298// however it does rely on undefined behaviour by passing UDT's through (...).
299//
300template <typename From, typename To>
301struct is_convertible_basic_impl
302{
303 static ::ndnboost::type_traits::no_type BOOST_TT_DECL _m_check(...);
304 static ::ndnboost::type_traits::yes_type BOOST_TT_DECL _m_check(To);
305 typedef typename add_lvalue_reference<From>::type lvalue_type;
306 typedef typename add_rvalue_reference<From>::type rvalue_type;
307 static lvalue_type _m_from;
308#ifdef BOOST_MSVC
309#pragma warning(push)
310#pragma warning(disable:4244)
311#if BOOST_WORKAROUND(BOOST_MSVC_FULL_VER, >= 140050000)
312#pragma warning(disable:6334)
313#endif
314#endif
315#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
316 BOOST_STATIC_CONSTANT(bool, value =
317 sizeof( _m_check(static_cast<rvalue_type>(_m_from)) ) == sizeof(::ndnboost::type_traits::yes_type)
318 );
319#else
320 BOOST_STATIC_CONSTANT(bool, value =
321 sizeof( _m_check(_m_from) ) == sizeof(::ndnboost::type_traits::yes_type)
322 );
323#endif
324#ifdef BOOST_MSVC
325#pragma warning(pop)
326#endif
327};
328
329#endif // is_convertible_impl
330
331#if defined(__DMC__)
332// As before, a static constant sometimes causes errors on Digital Mars.
333template <typename From, typename To>
334struct is_convertible_impl
335{
336 enum { value =
337 (::ndnboost::type_traits::ice_and<
338 ::ndnboost::type_traits::ice_or<
339 ::ndnboost::detail::is_convertible_basic_impl<From,To>::value,
340 ::ndnboost::is_void<To>::value
341 >::value,
342 ::ndnboost::type_traits::ice_not<
343 ::ndnboost::is_array<To>::value
344 >::value,
345 ::ndnboost::type_traits::ice_not<
346 ::ndnboost::is_function<To>::value
347 >::value
348 >::value) };
349};
350#elif !defined(__BORLANDC__) || __BORLANDC__ > 0x551
351template <typename From, typename To>
352struct is_convertible_impl
353{
354 BOOST_STATIC_CONSTANT(bool, value =
355 (::ndnboost::type_traits::ice_and<
356 ::ndnboost::type_traits::ice_or<
357 ::ndnboost::detail::is_convertible_basic_impl<From,To>::value,
358 ::ndnboost::is_void<To>::value
359 >::value,
360 ::ndnboost::type_traits::ice_not<
361 ::ndnboost::is_array<To>::value
362 >::value,
363 ::ndnboost::type_traits::ice_not<
364 ::ndnboost::is_function<To>::value
365 >::value
366 >::value)
367 );
368};
369#endif
370
371template <bool trivial1, bool trivial2, bool abstract_target>
372struct is_convertible_impl_select
373{
374 template <class From, class To>
375 struct rebind
376 {
377 typedef is_convertible_impl<From, To> type;
378 };
379};
380
381template <>
382struct is_convertible_impl_select<true, true, false>
383{
384 template <class From, class To>
385 struct rebind
386 {
387 typedef true_type type;
388 };
389};
390
391template <>
392struct is_convertible_impl_select<false, false, true>
393{
394 template <class From, class To>
395 struct rebind
396 {
397 typedef false_type type;
398 };
399};
400
401template <>
402struct is_convertible_impl_select<true, false, true>
403{
404 template <class From, class To>
405 struct rebind
406 {
407 typedef false_type type;
408 };
409};
410
411template <typename From, typename To>
412struct is_convertible_impl_dispatch_base
413{
414#if !BOOST_WORKAROUND(__HP_aCC, < 60700)
415 typedef is_convertible_impl_select<
416 ::ndnboost::is_arithmetic<From>::value,
417 ::ndnboost::is_arithmetic<To>::value,
418#ifndef BOOST_NO_IS_ABSTRACT
419 ::ndnboost::is_abstract<To>::value
420#else
421 false
422#endif
423 > selector;
424#else
425 typedef is_convertible_impl_select<false, false, false> selector;
426#endif
427 typedef typename selector::template rebind<From, To> isc_binder;
428 typedef typename isc_binder::type type;
429};
430
431template <typename From, typename To>
432struct is_convertible_impl_dispatch
433 : public is_convertible_impl_dispatch_base<From, To>::type
434{};
435
436//
437// Now add the full and partial specialisations
438// for void types, these are common to all the
439// implementation above:
440//
441#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
442# define TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2_PART1(trait,spec1,spec2,value) \
443 BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC2(trait,spec1,spec2,value) \
444 BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC2(trait,spec1,spec2 const,value) \
445 BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC2(trait,spec1,spec2 volatile,value) \
446 BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC2(trait,spec1,spec2 const volatile,value) \
447 /**/
448
449# define TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2(trait,spec1,spec2,value) \
450 TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2_PART1(trait,spec1,spec2,value) \
451 TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2_PART1(trait,spec1 const,spec2,value) \
452 TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2_PART1(trait,spec1 volatile,spec2,value) \
453 TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2_PART1(trait,spec1 const volatile,spec2,value) \
454 /**/
455
456 TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2(is_convertible,void,void,true)
457
458# undef TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2
459# undef TT_AUX_BOOL_CV_VOID_TRAIT_SPEC2_PART1
460
461#else
462 BOOST_TT_AUX_BOOL_TRAIT_IMPL_SPEC2(is_convertible,void,void,true)
463#endif // BOOST_NO_CV_VOID_SPECIALIZATIONS
464
465#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
466BOOST_TT_AUX_BOOL_TRAIT_IMPL_PARTIAL_SPEC2_1(typename To,is_convertible,void,To,false)
467BOOST_TT_AUX_BOOL_TRAIT_IMPL_PARTIAL_SPEC2_1(typename From,is_convertible,From,void,false)
468#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
469BOOST_TT_AUX_BOOL_TRAIT_IMPL_PARTIAL_SPEC2_1(typename To,is_convertible,void const,To,false)
470BOOST_TT_AUX_BOOL_TRAIT_IMPL_PARTIAL_SPEC2_1(typename To,is_convertible,void volatile,To,false)
471BOOST_TT_AUX_BOOL_TRAIT_IMPL_PARTIAL_SPEC2_1(typename To,is_convertible,void const volatile,To,false)
472BOOST_TT_AUX_BOOL_TRAIT_IMPL_PARTIAL_SPEC2_1(typename From,is_convertible,From,void const,false)
473BOOST_TT_AUX_BOOL_TRAIT_IMPL_PARTIAL_SPEC2_1(typename From,is_convertible,From,void volatile,false)
474BOOST_TT_AUX_BOOL_TRAIT_IMPL_PARTIAL_SPEC2_1(typename From,is_convertible,From,void const volatile,false)
475#endif
476#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
477
478} // namespace detail
479
480BOOST_TT_AUX_BOOL_TRAIT_DEF2(is_convertible,From,To,(::ndnboost::detail::is_convertible_impl_dispatch<From,To>::value))
481
482#else
483
484BOOST_TT_AUX_BOOL_TRAIT_DEF2(is_convertible,From,To,BOOST_IS_CONVERTIBLE(From,To))
485
486#endif
487
488} // namespace ndnboost
489
Jeff Thompson2277ce52013-08-01 17:34:11 -0700490#include <ndnboost/type_traits/detail/bool_trait_undef.hpp>
Jeff Thompsonf7d49942013-08-01 16:47:40 -0700491
492#endif // BOOST_TT_IS_CONVERTIBLE_HPP_INCLUDED