BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bslmf_isconvertible.h
Go to the documentation of this file.
1/// @file bslmf_isconvertible.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslmf_isconvertible.h -*-C++-*-
8#ifndef INCLUDED_BSLMF_ISCONVERTIBLE
9#define INCLUDED_BSLMF_ISCONVERTIBLE
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslmf_isconvertible bslmf_isconvertible
15/// @brief Provide a compile-time check for type conversion.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslmf
19/// @{
20/// @addtogroup bslmf_isconvertible
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslmf_isconvertible-purpose"> Purpose</a>
25/// * <a href="#bslmf_isconvertible-classes"> Classes </a>
26/// * <a href="#bslmf_isconvertible-description"> Description </a>
27/// * <a href="#bslmf_isconvertible-usage"> Usage </a>
28/// * <a href="#bslmf_isconvertible-example-1-select-function-based-on-type-convertibility"> Example 1: Select Function Based on Type Convertibility </a>
29///
30/// # Purpose {#bslmf_isconvertible-purpose}
31/// Provide a compile-time check for type conversion.
32///
33/// # Classes {#bslmf_isconvertible-classes}
34///
35/// - bsl::is_convertible: standard meta-function for type conversion checking
36/// - bsl::is_convertible_v: the result value of `bsl::is_convertible`
37/// - bslmf::IsConvertible: meta-function for type conversion checking
38///
39/// @see bslmf_integralconstant
40///
41/// # Description {#bslmf_isconvertible-description}
42/// This component defines two meta-functions,
43/// `bsl::is_convertible` and `BloombergLP::bslmf::IsConvertible` and a template
44/// variable `bsl::is_convertible_v`, that represents the result value of the
45/// `bsl::is_convertible` meta-function. All these meta-functions may be used
46/// to check whether an implicit conversion exists from one type to another.
47///
48/// When compiling on C++11 or later, both meta-functions are aliases to the
49/// standard library implementation std::is_convertible.
50///
51/// When compiling on C++03 `bsl::is_convertible` tries to meet the requirements
52/// of the `is_convertible` template defined in the C++11 standard [meta.rel] as
53/// much as possible but fails in some corner cases. One example of such a
54/// case:
55/// @code
56/// class A {};
57/// class B { public: B(A& ); };
58///
59/// BSLMF_ASSERT((!bsl::is_convertible<A, B>::value)); //<-- FAIL in C++03 mode
60/// @endcode
61///
62/// `bslmf::IsConvertible` was devised before `is_convertible` was standardized
63/// and is functionally equivalent except that `bsl::is_convertible` does not
64/// allow its template parameter types to be incomplete types according to the
65/// C++11 standard while `bslmf::IsConvertible` tests conversions involving
66/// incomplete types.
67///
68/// Note that `bsl::is_convertible` should be preferred over
69/// `bslmf::IsConvertible`, and in general, should be used by new components.
70/// Also note that `bsl::is_convertible` and `bslmf::IsConvertible` can produce
71/// compiler errors if the conversion is ambiguous. For example:
72/// @code
73/// struct A {};
74/// struct B : public A {};
75/// struct C : public A {};
76/// struct D : public B, public C {};
77///
78/// static int const C = bsl::is_convertible<D*, A*>::value; // ERROR!
79/// @endcode
80/// Also note that the template variable `is_convertible_v` is defined in the
81/// C++17 standard as an inline variable. If the current compiler supports the
82/// inline variable C++17 compiler feature, `bsl::is_convertible_v` is defined
83/// as an `inline constexpr bool` variable. Otherwise, if the compiler supports
84/// the variable templates C++14 compiler feature, `bsl::is_convertible_v` is
85/// defined as a non-inline `constexpr bool` variable. See
86/// `BSLS_COMPILERFEATURES_SUPPORT_INLINE_VARIABLES` and
87/// `BSLS_COMPILERFEATURES_SUPPORT_VARIABLE_TEMPLATES` macros in
88/// bsls_compilerfeatures component for details.
89///
90/// ## Usage {#bslmf_isconvertible-usage}
91///
92///
93/// In this section we show intended use of this component.
94///
95/// ### Example 1: Select Function Based on Type Convertibility {#bslmf_isconvertible-example-1-select-function-based-on-type-convertibility}
96///
97///
98/// The `bsl::is_convertible` meta-function can be used to select an appropriate
99/// function (at compile time) based on the convertibility of one type to
100/// another without causing a compiler error by actually trying the conversion.
101///
102/// First, we define two classes, `Foo` and `Bar`. The `Foo` class has an
103/// explict constructor from `int`, an implicit conversion operator that returns
104/// an integer value while the `Bar` class does neither:
105/// @code
106/// class Foo {
107/// // DATA
108/// int d_value;
109///
110/// public:
111/// // CREATORS
112/// explicit Foo(int value) : d_value(value) {}
113///
114/// // ACCESSORS
115/// operator int() const { return d_value; }
116/// };
117///
118/// class Bar {};
119/// @endcode
120/// Then, we run:
121/// @code
122/// assert(false == (bsl::is_convertible<int, Foo>::value));
123/// assert(false == (bsl::is_convertible<int, Bar>::value));
124///
125/// assert(true == (bsl::is_convertible<Foo, int>::value));
126/// assert(false == (bsl::is_convertible<Bar, int>::value));
127/// @endcode
128/// Note that `int` to `Foo` is false, even though `Foo` has a constructor that
129/// takes an `int`. This is because that constructor is explicit, and
130/// `is_converitble` ignores explicit constructors.
131///
132/// Next, we go on to demonstrate how this could be used. Suppose we are
133/// implementing a `convertToInt` template method that converts a given object
134/// of the (template parameter) `t_TYPE` to `int` type, and returns the integer
135/// value. If the given object can not convert to `int`, return 0. The method
136/// calls an overloaded function, `getIntValue`, to get the converted integer
137/// value. The idea is to invoke one version of `getIntValue` if the type
138/// provides a conversion operator that returns an integer value, and another
139/// version if the type does not provide such an operator.
140///
141/// We define the first `getIntValue` function that takes a `bsl::false_type` as
142/// its last argument, whereas the second `getIntValue` function takes a
143/// `bsl::true_type` object. The result of the `bsl::is_convertible`
144/// meta-function (i.e., its `type` member) is used to create the last argument
145/// passed to `getIntValue`. Neither version of `getIntValue` makes use of this
146/// argument -- it is used only to differentiate the argument list so we can
147/// overload the function.
148/// @code
149/// template <class t_TYPE>
150/// inline
151/// int getIntValue(t_TYPE *, bsl::false_type)
152/// {
153/// // Return 0 because the specified 't_TYPE' is not convertible to the
154/// // 'int' type.
155///
156/// return 0;
157/// }
158///
159/// template <class t_TYPE>
160/// inline
161/// int getIntValue(t_TYPE *object, bsl::true_type)
162/// {
163/// // Return the integer value converted from the specified 'object' of
164/// // the (template parameter) 't_TYPE'.
165///
166/// return int(*object);
167/// }
168/// @endcode
169/// Now, we define our `convertToInt` method:
170/// @code
171/// template <class t_TYPE>
172/// inline
173/// int convertToInt(t_TYPE *object)
174/// {
175/// typedef typename bsl::is_convertible<t_TYPE,
176/// int>::type CanConvertToInt;
177/// return getIntValue(object, CanConvertToInt());
178/// }
179/// @endcode
180/// Notice that we use `bsl::is_convertible` to get a `bsl::false_type` or
181/// `bsl::true_type`, and then call the corresponding overloaded `getIntValue`
182/// method.
183///
184/// Finally, we call our finished product and observe the return values:
185/// @code
186/// Foo foo(99);
187/// Bar bar;
188///
189/// assert(99 == convertToInt(&foo));
190/// assert(0 == convertToInt(&bar));
191/// @endcode
192/// @}
193/** @} */
194/** @} */
195
196/** @addtogroup bsl
197 * @{
198 */
199/** @addtogroup bslmf
200 * @{
201 */
202/** @addtogroup bslmf_isconvertible
203 * @{
204 */
205
206#include <bslscm_version.h>
207
208#include <bslmf_addconst.h>
210#include <bslmf_assert.h>
211#include <bslmf_conditional.h>
212#include <bslmf_enableif.h>
214#include <bslmf_isarray.h>
215#include <bslmf_isfunction.h>
216#include <bslmf_isfundamental.h>
217#include <bslmf_ispointer.h>
218#include <bslmf_isvoid.h>
219#include <bslmf_matchanytype.h>
220#include <bslmf_removecv.h>
221
223#include <bsls_keyword.h>
224#include <bsls_platform.h>
225
226#ifdef BSLS_COMPILERFEATURES_SUPPORT_TRAITS_HEADER
227# include <type_traits>
228#endif // BSLS_COMPILERFEATURES_SUPPORT_TRAITS_HEADER
229
230#ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
231#include <bsls_nativestd.h>
232#endif // BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
233
234#if defined(BSLS_COMPILERFEATURES_SUPPORT_TRAITS_HEADER) && \
235 !(defined(BSLS_PLATFORM_CMP_MSVC) && BSLS_PLATFORM_CMP_VERSION <= 1900)
236 // The Microsoft implementation of native traits allows binding of rvalues
237 // (including temporaries invented for conversion) to 'const volatile &'
238 // references. Early versions also do not correctly disallow conversion
239 // from itself for types that are neither copy- nor move-constructible.
240# define BSLMF_ISCONVERTIBLE_USE_NATIVE_TRAITS
241#endif
242
243namespace bsl {
244
245template <class t_FROM_TYPE, class t_TO_TYPE>
246struct is_convertible;
247
248#ifdef BSLS_COMPILERFEATURES_SUPPORT_VARIABLE_TEMPLATES
249/// This template variable represents the result value of the
250/// `bsl::is_convertible` meta-function.
251template <class t_FROM_TYPE, class t_TO_TYPE>
252BSLS_KEYWORD_INLINE_VARIABLE constexpr bool is_convertible_v =
253 is_convertible<t_FROM_TYPE, t_TO_TYPE>::value;
254#endif
255
256} // close namespace bsl
257
258
259namespace bslmf {
260
261 // =========================================
262 // private class IsConvertible_CheckComplete
263 // =========================================
264
265template <class t_TYPE,
269 typedef t_TYPE type;
270
271 enum { k_CHECK_COMPLETE = sizeof(t_TYPE) };
272};
273
274template <class t_TYPE>
275struct IsConvertible_CheckComplete<t_TYPE&, false>
277 typedef t_TYPE& type;
278};
279
280#if defined(BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES)
281template <class t_TYPE>
282struct IsConvertible_CheckComplete<t_TYPE&&, false>
284 typedef t_TYPE && type;
285};
286#endif
287
288template <class t_TYPE>
289struct IsConvertible_CheckComplete<t_TYPE, true> {
290 typedef t_TYPE type;
291};
292
293#if !defined(BSLS_PLATFORM_CMP_IBM) // IBM rejects this valid specialization
294template <class t_TYPE>
295struct IsConvertible_CheckComplete<t_TYPE[], false> {
296 typedef t_TYPE type[];
297};
298#endif
299
300} // close package namespace
301
302
303#ifdef BSLMF_ISCONVERTIBLE_USE_NATIVE_TRAITS
304
305namespace bsl {
306
307template <class t_FROM_TYPE, class t_TO_TYPE>
308struct is_convertible
310 bool,
311 ::std::is_convertible<
312 typename BloombergLP::bslmf::IsConvertible_CheckComplete<
313 t_FROM_TYPE>::type,
314 typename BloombergLP::bslmf::IsConvertible_CheckComplete<
315 t_TO_TYPE>::type>::value> {
316};
317
318} // close namespace bsl
319#else
320
321
322namespace bslmf {
323
324 // ==========================
325 // struct IsConvertible_Match
326 // ==========================
327
328/// This `struct` provides functions to check for successful conversion
329/// matches. Sun CC 5.2 requires that this `struct` not be nested within
330/// `IsConvertible_Imp`.
331///
332/// See @ref bslmf_isconvertible
334
335 typedef struct { char a; } yes_type;
336 typedef struct { char a[2]; } no_type;
337
338 /// Return @ref yes_type if called on `IsConvertible_Match` type.
340
341#if !defined(BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES)
342 /// Return @ref yes_type if the (template parameter) `t_TYPE` is
343 /// `IsConvertible_Match`, and `no_type` otherwise.
344 template <class t_TYPE>
345 static no_type match(const t_TYPE&);
346
347 /// Return @ref yes_type if the (template parameter) `t_TYPE` is
348 /// `IsConvertible_Match` and `no_type` otherwise.
349 template <class t_TYPE>
350 static no_type match(const volatile t_TYPE&);
351
352 /// Return @ref yes_type if the (template parameter) `t_TYPE` is
353 /// `IsConvertible_Match` and `no_type` otherwise.
354 template <class t_TYPE>
355 static typename
357 match(t_TYPE&);
358#else
359 template <class t_TYPE>
360 static no_type match(t_TYPE&&);
361 // Return @ref yes_type if the (template parameter) 't_TYPE' is
362 // 'IsConvertible_Match', and 'no_type' otherwise.
363#endif
364};
365
366 // ========================
367 // struct IsConvertible_Imp
368 // ========================
369
370/// This `struct` template implements the meta-function to determine type
371/// conversion between the (template parameter) `t_FROM_TYPE` and the
372/// (template parameter) `t_TO_TYPE` where the conversion to the `t_TO_TYPE`
373/// is not necessarily the same as conversion to `const t_TO_TYPE&`.
374///
375///
376/// \note Note that significant documentation about the details of this
377/// implementation can be found in `bslmf_isconvertible.cpp`.
378///
379/// See @ref bslmf_isconvertible
380template <class t_FROM_TYPE,
381 class t_TO_TYPE
382#if defined(BSLS_PLATFORM_CMP_GNU) || defined(BSLS_PLATFORM_CMP_CLANG)
383 ,
384 int IS_FROM_FUNDAMENTAL = bsl::is_fundamental<t_FROM_TYPE>::value,
385 int IS_TO_FUNDAMENTAL = bsl::is_fundamental<t_TO_TYPE>::value
386#endif
387 >
389
390 private:
391 /// A unique (empty) type returned by the comma operator.
392 struct Test
393 {
394
395 /// Return a reference to type `IsConvertible_Match`.
396 IsConvertible_Match& operator, (t_TO_TYPE) const;
397 };
398
399 public:
400
401#ifdef BSLS_PLATFORM_CMP_MSVC
402# pragma warning(push)
403# pragma warning(disable: 4244) // loss of precision warning ignored
404#endif
405 enum {
406
409 (Test(), TypeRep<t_FROM_TYPE>::rep()))))
410 // Return the convertibility between 't_FROM_TYPE' and 't_TO_TYPE'.
411 // This is set by invoking the 'operator,' method having 'Test&' on
412 // the left and 't_FROM_TYPE' on the right. The 'value' is 'true' if
413 // 't_FROM_TYPE' is convertible to 't_TO_TYPE', and 'false' otherwise.
414 };
415
416#ifdef BSLS_PLATFORM_CMP_MSVC
417# pragma warning(pop)
418#endif
419
420 /// This `typedef` returns `bsl::true_type` if `t_FROM_TYPE` is
421 /// convertible to `t_TO_TYPE`, and `bsl::false_type` otherwise.
423};
424
425#if 0 // defined(BSLS_PLATFORM_CMP_GNU) || defined(BSLS_PLATFORM_CMP_CLANG)
426// The following template partial specializations produce the same results as
427// the unspecialized template would, but avoid generating conversion warnings
428// on the affected compilers. However, there is one known bug in this block of
429// code (reported by the test driver, not yet tracked down) and experimentally
430// removing it seems to clear the bug, without raising the feared warnings on
431// supported gcc platforms - although it still raises a few warnings with gcc
432// 4.3.5.
433
434#define BSLMF_ISCONVERTIBLE_SAMETYPEVALUE(t_VALUE, \
435 t_FROM, \
436 t_TO, \
437 t_FROM_FUND, \
438 t_TO_FUND) \
439 template <class t_TYPE> \
440 struct IsConvertible_Imp<t_FROM, t_TO, t_FROM_FUND, t_TO_FUND> \
441 : bsl::integral_constant<bool, VALUE> { \
442 };
443 // This partial specialization of 'bslmf::IsConvertible_Imp' derives from
444 // 'bsl::integral_constant' having the specified macro argument 'VALUE'.
445 // The specified macro arguments 't_FROM' and 't_TO' are cv-qualified type
446 // expressions constructed out of the (template parameter) 't_TYPE'.
447
448#define BSLMF_ISCONVERTIBLE_VALUE(t_VALUE, \
449 t_FROM, \
450 t_TO, \
451 t_FROM_FUND, \
452 t_TO_FUND) \
453 template <class t_FROM_TYPE, class t_TO_TYPE> \
454 struct IsConvertible_Imp<t_FROM, t_TO, t_FROM_FUND, t_TO_FUND> \
455 : bsl::integral_constant<bool, t_VALUE> { \
456 };
457 // This partial specialization of 'bslmf::IsConvertible_Imp' derives from
458 // 'bsl::integral_constant' having the specified macro argument 't_VALUE'.
459 // The specified macro arguments 't_FROM' and 't_TO' are cv-qualified type
460 // expressions constructed out of 't_FROM_TYPE' and 't_TO_TYPE',
461 // respectively.
462
463#define BSLMF_ISCONVERTIBLE_FORWARD(t_FROM, t_TO, t_FROM_FUND, t_TO_FUND) \
464 template <class t_FROM_TYPE, class t_TO_TYPE> \
465 struct IsConvertible_Imp<t_FROM, t_TO, t_FROM_FUND, t_TO_FUND> \
466 : IsConvertible_Imp<t_FROM, t_TO, 0, 0> { \
467 };
468 // This partial specialization of 'bslmf::IsConvertible_Imp' applies the
469 // general mechanism for non-fundamental types. The specified macro
470 // arguments 't_FROM' and 't_TO' are cv-qualified type expressions
471 // constructed out of 't_FROM_TYPE' and 't_TO_TYPE', respectively.
472
473BSLMF_ISCONVERTIBLE_SAMETYPEVALUE(0,
474 const volatile t_TYPE,
475 const t_TYPE&,
476 1,
477 1)
478BSLMF_ISCONVERTIBLE_SAMETYPEVALUE(0,
479 volatile t_TYPE,
480 const t_TYPE&,
481 1,
482 1)
483 // These two partial specializations are instantiated when a (possibly
484 // 'const'-qualified) 'volatile' fundamental type is tested for
485 // convertibility to its 'const' reference type. The conversion shall
486 // fail.
487
488BSLMF_ISCONVERTIBLE_VALUE(1,
489 const volatile t_FROM_TYPE,
490 const t_TO_TYPE&,
491 1,
492 1)
493BSLMF_ISCONVERTIBLE_VALUE(1,
494 volatile t_FROM_TYPE,
495 const t_TO_TYPE&,
496 1,
497 1)
498 // These two partial specializations are instantiated when a (possibly
499 // 'const'-qualified) 'volatile' type is tested for convertibility to the
500 // 'const' reference type of another fundamental type. These partial
501 // specializations will be picked up if the previous two fail to match.
502 // The conversion shall succeed.
503
504BSLMF_ISCONVERTIBLE_VALUE(1, const t_FROM_TYPE, const t_TO_TYPE&, 1, 1)
505BSLMF_ISCONVERTIBLE_VALUE(1, t_FROM_TYPE, const t_TO_TYPE&, 1, 1)
506 // These two partial specializations are instantiated when a (possibly
507 // 'const'-qualified) fundamental type is tested for convertibility to the
508 // 'const' reference type of another fundamental type. These partial
509 // specializations will be picked up if the previous two fail to match.
510 // The conversion shall succeed.
511
512BSLMF_ISCONVERTIBLE_FORWARD(const volatile t_FROM_TYPE,
513 const volatile t_TO_TYPE&, 1, 1)
514BSLMF_ISCONVERTIBLE_FORWARD( volatile t_FROM_TYPE,
515 const volatile t_TO_TYPE&, 1, 1)
516BSLMF_ISCONVERTIBLE_FORWARD(const t_FROM_TYPE,
517 const volatile t_TO_TYPE&, 1, 1)
518BSLMF_ISCONVERTIBLE_FORWARD( t_FROM_TYPE,
519 const volatile t_TO_TYPE&, 1, 1)
520 // These four partial specializations are instantiated when a (possibly
521 // cv-qualified) fundamental type is tested for convertibility to the
522 // 'const volatile' reference type of another fundamental type.
523
524BSLMF_ISCONVERTIBLE_FORWARD(const volatile t_FROM_TYPE,
525 volatile t_TO_TYPE&, 1, 1)
526BSLMF_ISCONVERTIBLE_FORWARD( volatile t_FROM_TYPE,
527 volatile t_TO_TYPE&, 1, 1)
528BSLMF_ISCONVERTIBLE_FORWARD(const t_FROM_TYPE,
529 volatile t_TO_TYPE&, 1, 1)
530BSLMF_ISCONVERTIBLE_FORWARD( t_FROM_TYPE,
531 volatile t_TO_TYPE&, 1, 1)
532 // These four partial specializations are instantiated when a (possibly
533 // cv-qualified) fundamental type is tested for convertibility to the
534 // 'volatile' reference type of another fundamental type.
535
536BSLMF_ISCONVERTIBLE_FORWARD(const volatile t_FROM_TYPE, t_TO_TYPE&, 1, 1)
537BSLMF_ISCONVERTIBLE_FORWARD( volatile t_FROM_TYPE, t_TO_TYPE&, 1, 1)
538BSLMF_ISCONVERTIBLE_FORWARD(const t_FROM_TYPE, t_TO_TYPE&, 1, 1)
539BSLMF_ISCONVERTIBLE_FORWARD( t_FROM_TYPE, t_TO_TYPE&, 1, 1)
540 // These four partial specializations are instantiated when a (possibly
541 // cv-qualified) fundamental type is tested for convertibility to the
542 // non-cv-qualified reference type of another fundamental type.
543
544template <class t_FROM_TYPE, class t_TO_TYPE>
545struct IsConvertible_Imp<const t_FROM_TYPE, t_TO_TYPE, 1, 1>
546 : IsConvertible_Imp<const t_FROM_TYPE, double, 0, 0>::type {
547 // This partial specialization is instantiated when the 'const' (template
548 // parameter) fundamental 't_FROM_TYPE' is tested for convertibility to
549 // another (template parameter) fundamental 't_TO_TYPE'. This partial
550 // specialization derives from
551 // 'IsConvertible_Imp<const t_FROM_TYPE, double, 0, 0>' to avoid any
552 // compilation warnings in case the 't_TO_TYPE' is an integral type and
553 // 't_FROM_TYPE' is a floating-point type.
554};
555
556template <class t_FROM_TYPE, class t_TO_TYPE>
557struct IsConvertible_Imp<t_FROM_TYPE, t_TO_TYPE, 1, 1>
558 : IsConvertible_Imp<t_FROM_TYPE, double, 0, 0>::type {
559 // This partial specialization is instantiated when the (template
560 // parameter) fundamental 't_FROM_TYPE' is tested for convertibility to
561 // another (template parameter) fundamental 't_TO_TYPE'. This partial
562 // specialization derives from
563 // 'IsConvertible_Imp<t_FROM_TYPE, double, 0, 0>' to avoid any compilation
564 // warnings in case that the 't_FROM_TYPE' is a floating-point type and
565 // 't_TO_TYPE' is an integral type.
566};
567
568template <class t_FROM_TYPE, class t_TO_TYPE>
569struct IsConvertible_Imp<t_FROM_TYPE, t_TO_TYPE, 0, 1>
570 : IsConvertible_Imp<t_FROM_TYPE, double, 0, 0>::type {
571 // This partial specialization is instantiated when the (template
572 // parameter) 't_FROM_TYPE' is a non-fundamental type, and the (template
573 // parameter) 't_TO_TYPE' is a non-'void' fundamental type. This partial
574 // specialization derives from
575 // 'IsConvertible_Imp<t_FROM_TYPE, double, 0, 0>' to avoid any compilation
576 // warnings in case that the 't_FROM_TYPE' is a floating-point type and the
577 // 't_TO_TYPE' is an integral type.
578};
579
580template <class t_FROM_TYPE, class t_TO_TYPE>
581struct IsConvertible_Imp<t_FROM_TYPE, t_TO_TYPE, 1, 0>
582 : IsConvertible_Imp<int, t_TO_TYPE, 0, 0>::type {
583 // This partial specialization is instantiated when the (template
584 // parameter) 't_FROM_TYPE' is a non-'void' fundamental type, and the
585 // (template parameter) 't_TO_TYPE' is a non-fundamental type. This
586 // partial specialization derives from
587 // 'IsConvertible_Imp<int, t_TO_TYPE, 0, 0>' to avoid any compilation
588 // warnings in case that the 't_FROM_TYPE' is a floating-point type and the
589 // 't_TO_TYPE' is an integral type.
590};
591
592#undef BSLMF_ISCONVERTIBLE_SAMETYPEVALUE
593#undef BSLMF_ISCONVERTIBLE_VALUE
594#undef BSLMF_ISCONVERTIBLE_FORWARD
595
596#endif
597
598template <class t_TO_TYPE>
600: bsl::add_lvalue_reference<typename bsl::add_const<
601 typename bsl::remove_cv<t_TO_TYPE>::type>::type> {
602};
603
604template <class t_FROM_TYPE, class t_TO_TYPE>
607 bsl::is_void<t_FROM_TYPE>::value ||
608 bsl::is_array<t_TO_TYPE>::value ||
609 bsl::is_function<t_TO_TYPE>::value> {
610};
611
612template <class t_FROM_TYPE, class t_TO_TYPE>
615 IsConvertible_IsNeverConvertible<t_FROM_TYPE, t_TO_TYPE>::value,
616 bsl::false_type,
617 IsConvertible_Imp<t_FROM_TYPE,
618 typename IsConvertible_LazyTrait<t_TO_TYPE>::type> >::
619 type {
620};
621
622template <class t_FROM_TYPE, class t_TO_TYPE>
625 bsl::is_void<t_TO_TYPE>::value,
626 typename bsl::is_void<t_FROM_TYPE>::type,
627 IsConvertible_FilterNeverConvertible<
628 typename IsConvertible_CheckComplete<t_FROM_TYPE>::type,
629 typename IsConvertible_CheckComplete<t_TO_TYPE>::type> >::type {
630};
631
632} // close package namespace
633
634
635namespace bsl {
636
637 // ==============================
638 // struct is_convertible_dispatch
639 // ==============================
640
641/// This `struct` template implements the `is_convertible_dispatch`
642/// meta-function defined in the C++11 standard [meta.rel] to determine if
643/// the (template parameter) `t_FROM_TYPE` is convertible to the (template
644/// parameter) `t_TO_TYPE`. This `struct` derives from `bsl::true_type` if
645/// the `t_FROM_TYPE` is convertible to `t_TO_TYPE`, and from `bsl::false_type` otherwise.
646///
647/// \note Note that both `t_FROM_TYPE` and
648/// `t_TO_TYPE` should be complete types, arrays of unknown bound, or
649/// (possibly cv-qualified) `void` types.
650template <class t_FROM_TYPE, class t_TO_TYPE>
652: BloombergLP::bslmf::IsConvertible_Conditional<t_FROM_TYPE, t_TO_TYPE>::type {
653};
654
655/// This set of rules corresponds with the reference binding rules in c++11,
656/// where the specification of `is_convertible_dispatch` relies on
657/// rvalue-references. We must supply these specializations directly in
658/// order to support C++03 compilers that do not have a good substitute for
659/// rvalue-references, as using `const &` instead produces subtly different
660/// results in some cases.
661template <class t_TYPE>
668
669// Some compilers need explicit guidance on a few of the reference-binding
670// conversions. All compilers get most of these correct, but once a few
671// specializations are added, the full set is required to avoid ambiguities.
672
673template <class t_TYPE>
674struct is_convertible_dispatch<t_TYPE, const t_TYPE&> : true_type {
675};
676
677template <class t_TYPE>
678struct is_convertible_dispatch<t_TYPE, volatile t_TYPE&> : false_type {
679};
680
681template <class t_TYPE>
682struct is_convertible_dispatch<t_TYPE, const volatile t_TYPE&> : false_type {
683};
684
685template <class t_TYPE>
686struct is_convertible_dispatch<const t_TYPE, t_TYPE&> : false_type {
687};
688
689template <class t_TYPE>
690struct is_convertible_dispatch<const t_TYPE, const t_TYPE&> : true_type {
691};
692
693template <class t_TYPE>
694struct is_convertible_dispatch<const t_TYPE, volatile t_TYPE&> : false_type {
695};
696
697template <class t_TYPE>
698struct is_convertible_dispatch<const t_TYPE, const volatile t_TYPE&>
699: false_type {
700};
701
702template <class t_TYPE>
703struct is_convertible_dispatch<volatile t_TYPE, t_TYPE&> : false_type {
704};
705
706template <class t_TYPE>
707struct is_convertible_dispatch<volatile t_TYPE, const t_TYPE&> : false_type {
708};
709
710template <class t_TYPE>
711struct is_convertible_dispatch<volatile t_TYPE, volatile t_TYPE&>
712: false_type {
713};
714
715template <class t_TYPE>
716struct is_convertible_dispatch<volatile t_TYPE, const volatile t_TYPE&>
717: false_type {
718};
719
720template <class t_TYPE>
721struct is_convertible_dispatch<const volatile t_TYPE, t_TYPE&> : false_type {
722};
723
724template <class t_TYPE>
725struct is_convertible_dispatch<const volatile t_TYPE, const t_TYPE&>
726: false_type {
727};
728
729template <class t_TYPE>
730struct is_convertible_dispatch<const volatile t_TYPE, volatile t_TYPE&>
731: false_type {
732};
733
734template <class t_TYPE>
735struct is_convertible_dispatch<const volatile t_TYPE, const volatile t_TYPE&>
736: false_type {
737};
738
739// The next group of partial specializations deal with various cases of
740// converting to an lvalue-reference, which we make explicitly conform to the
741// C++11 idiom of converting from an rvalue (which may be an lvalue-reference).
742
743template <class t_TYPE>
744struct is_convertible_dispatch<t_TYPE&, t_TYPE&> : true_type {
745};
746
747template <class t_TYPE>
748struct is_convertible_dispatch<t_TYPE&, const t_TYPE&> : true_type {
749};
750
751template <class t_TYPE>
752struct is_convertible_dispatch<t_TYPE&, volatile t_TYPE&> : true_type {
753};
754
755template <class t_TYPE>
756struct is_convertible_dispatch<t_TYPE&, const volatile t_TYPE&> : true_type {
757};
758
759template <class t_TYPE>
760struct is_convertible_dispatch<const t_TYPE&, t_TYPE&> : false_type {
761};
762
763template <class t_TYPE>
764struct is_convertible_dispatch<const t_TYPE&, const t_TYPE&> : true_type {
765};
766
767template <class t_TYPE>
768struct is_convertible_dispatch<const t_TYPE&, volatile t_TYPE&> : false_type {
769};
770
771template <class t_TYPE>
772struct is_convertible_dispatch<const t_TYPE&, const volatile t_TYPE&>
773: true_type {
774};
775
776template <class t_TYPE>
777struct is_convertible_dispatch<volatile t_TYPE&, t_TYPE&> : false_type {
778};
779
780template <class t_TYPE>
781struct is_convertible_dispatch<volatile t_TYPE&, const t_TYPE&> : false_type {
782};
783
784template <class t_TYPE>
785struct is_convertible_dispatch<volatile t_TYPE&, volatile t_TYPE&>
786: true_type {
787};
788
789template <class t_TYPE>
790struct is_convertible_dispatch<volatile t_TYPE&, const volatile t_TYPE&>
791: true_type {
792};
793
794template <class t_TYPE>
795struct is_convertible_dispatch<const volatile t_TYPE&, t_TYPE&> : false_type {
796};
797
798template <class t_TYPE>
799struct is_convertible_dispatch<const volatile t_TYPE&, const t_TYPE&>
800: false_type {
801};
802
803template <class t_TYPE>
804struct is_convertible_dispatch<const volatile t_TYPE&, volatile t_TYPE&>
805: false_type {
806};
807
808template <class t_TYPE>
809struct is_convertible_dispatch<const volatile t_TYPE&, const volatile t_TYPE&>
810: true_type {
811};
812
813/// Correct handling of non-fundamental volatile conversions to self.
814///
815/// \note Note that this is not trivially true, but tests that `t_TYPE` is copy (or
816/// move) constructible.
817template <class t_TYPE>
818struct is_convertible_dispatch<volatile t_TYPE, t_TYPE>
819: BloombergLP::bslmf::IsConvertible_Conditional<t_TYPE, t_TYPE>::type {
820};
821
822template <class t_FROM_TYPE, class t_TO_TYPE>
823struct is_convertible_dispatch<t_FROM_TYPE, volatile t_TO_TYPE&> : false_type {
824};
825
826template <class t_FROM_TYPE, class t_TO_TYPE>
827struct is_convertible_dispatch<t_FROM_TYPE, const volatile t_TO_TYPE&>
828: false_type {
829};
830
831template <class t_FROM_TYPE, class t_TO_TYPE>
832struct is_convertible_dispatch<volatile t_FROM_TYPE&, volatile t_TO_TYPE&>
834};
835
836template <class t_FROM_TYPE, class t_TO_TYPE>
837struct is_convertible_dispatch<volatile t_FROM_TYPE&,
838 const volatile t_TO_TYPE&>
840};
841
842 // =====================
843 // struct is_convertible
844 // =====================
845
846template <class t_FROM_TYPE>
847struct EffectiveFromType : conditional<is_fundamental<t_FROM_TYPE>::value ||
848 is_pointer<t_FROM_TYPE>::value,
849 typename remove_cv<t_FROM_TYPE>::type,
850 t_FROM_TYPE> {
851};
852
853template <class t_FROM_TYPE, class t_TO_TYPE>
854struct is_convertible_dispatch<volatile t_FROM_TYPE&, t_TO_TYPE>
858 typename BloombergLP::bslmf::IsConvertible_Conditional<
859 volatile t_FROM_TYPE,
860 t_TO_TYPE>::type>::type {
861};
862
863/// This `struct` template implements the `is_convertible_dispatch`
864/// meta-function defined in the C++11 standard [meta.rel] to determine if
865/// the (template parameter) `t_FROM_TYPE` is convertible to the (template
866/// parameter) `t_TO_TYPE`. This `struct` derives from `bsl::true_type` if
867/// the `t_FROM_TYPE` is convertible to `t_TO_TYPE`, and from `bsl::false_type` otherwise.
868///
869/// \note Note that both `t_FROM_TYPE` and
870/// `t_TO_TYPE` should be complete types, arrays of unknown bound, or
871/// (possibly cv-qualified) `void` types.
872template <class t_FROM_TYPE, class t_TO_TYPE>
874: is_convertible_dispatch<typename EffectiveFromType<t_FROM_TYPE>::type,
875 t_TO_TYPE>::type {
876};
877
878} // close namespace bsl
879#endif
880
881
882namespace bslmf {
883
884 // ====================
885 // struct IsConvertible
886 // ====================
887
888/// This `struct` template implements a meta-function to determine if the
889/// (template parameter) `t_FROM_TYPE` is convertible to the (template
890/// parameter) `t_TO_TYPE`. This `struct` derives from `bsl::true_type` if
891/// the `t_FROM_TYPE` is convertible to `t_TO_TYPE`, and from `bsl::false_type` otherwise.
892///
893/// \note Note that both `t_FROM_TYPE` and
894/// `t_TO_TYPE` should be complete types, arrays of unknown bound, or
895/// (possibly cv-qualified) `void` types.
896template <class t_FROM_TYPE, class t_TO_TYPE>
897struct IsConvertible : bsl::is_convertible<t_FROM_TYPE, t_TO_TYPE>::type {
898};
899
900} // close package namespace
901
902#ifndef BDE_OPENSOURCE_PUBLICATION // BACKWARD_COMPATIBILITY
903// ============================================================================
904// BACKWARD COMPATIBILITY
905// ============================================================================
906
907#ifdef bslmf_IsConvertible
908#undef bslmf_IsConvertible
909#endif
910/// This alias is defined for backward compatibility.
911#define bslmf_IsConvertible bslmf::IsConvertible
912#endif // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY
913
914
915
916#endif // ! defined(INCLUDED_BSLMF_ISCONVERTIBLE)
917
918// ----------------------------------------------------------------------------
919// Copyright 2013 Bloomberg Finance L.P.
920//
921// Licensed under the Apache License, Version 2.0 (the "License");
922// you may not use this file except in compliance with the License.
923// You may obtain a copy of the License at
924//
925// http://www.apache.org/licenses/LICENSE-2.0
926//
927// Unless required by applicable law or agreed to in writing, software
928// distributed under the License is distributed on an "AS IS" BASIS,
929// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
930// See the License for the specific language governing permissions and
931// limitations under the License.
932// ----------------------------- END-OF-FILE ----------------------------------
933
934/** @} */
935/** @} */
936/** @} */
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_KEYWORD_INLINE_VARIABLE
Definition bsls_keyword.h:665
Definition bdlat_valuetypefunctions.h:939
Definition bdlbb_blob.h:579
Definition bslmf_isconvertible.h:850
Definition bslmf_addlvaluereference.h:128
Definition bslmf_conditional.h:123
Definition bslmf_enableif.h:530
Definition bslmf_integralconstant.h:261
Definition bslmf_isconst.h:145
Definition bslmf_isconvertible.h:652
Definition bslmf_isconvertible.h:875
Definition bslmf_isfunction.h:232
Definition bslmf_isfundamental.h:330
Definition bslmf_isreference.h:137
Definition bslmf_isvoid.h:138
t_TYPE type
Definition bslmf_isconvertible.h:290
t_TYPE & type
Definition bslmf_isconvertible.h:277
Definition bslmf_isconvertible.h:268
@ k_CHECK_COMPLETE
Definition bslmf_isconvertible.h:271
t_TYPE type
Definition bslmf_isconvertible.h:269
Definition bslmf_isconvertible.h:629
Definition bslmf_isconvertible.h:619
Definition bslmf_isconvertible.h:388
@ value
Definition bslmf_isconvertible.h:407
bsl::integral_constant< bool, value > type
Definition bslmf_isconvertible.h:422
Definition bslmf_isconvertible.h:609
Definition bslmf_isconvertible.h:601
Definition bslmf_isconvertible.h:336
Definition bslmf_isconvertible.h:335
char a
Definition bslmf_isconvertible.h:335
Definition bslmf_isconvertible.h:333
static yes_type match(IsConvertible_Match &)
Return yes_type if called on IsConvertible_Match type.
static no_type match(const t_TYPE &)
static no_type match(const volatile t_TYPE &)
static bsl::enable_if< bsl::is_function< t_TYPE >::value, no_type >::type match(t_TYPE &)
Definition bslmf_isconvertible.h:897
Definition bslmf_matchanytype.h:195