BDE 4.14.0 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`.
332
333 typedef struct { char a; } yes_type;
334 typedef struct { char a[2]; } no_type;
335
336 /// Return @ref yes_type if called on `IsConvertible_Match` type.
338
339#if !defined(BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES)
340 /// Return @ref yes_type if the (template parameter) `t_TYPE` is
341 /// `IsConvertible_Match`, and `no_type` otherwise.
342 template <class t_TYPE>
343 static no_type match(const t_TYPE&);
344
345 /// Return @ref yes_type if the (template parameter) `t_TYPE` is
346 /// `IsConvertible_Match` and `no_type` otherwise.
347 template <class t_TYPE>
348 static no_type match(const volatile t_TYPE&);
349
350 /// Return @ref yes_type if the (template parameter) `t_TYPE` is
351 /// `IsConvertible_Match` and `no_type` otherwise.
352 template <class t_TYPE>
353 static typename
355 match(t_TYPE&);
356#else
357 template <class t_TYPE>
358 static no_type match(t_TYPE&&);
359 // Return @ref yes_type if the (template parameter) 't_TYPE' is
360 // 'IsConvertible_Match', and 'no_type' otherwise.
361#endif
362};
363
364 // ========================
365 // struct IsConvertible_Imp
366 // ========================
367
368/// This `struct` template implements the meta-function to determine type
369/// conversion between the (template parameter) `t_FROM_TYPE` and the
370/// (template parameter) `t_TO_TYPE` where the conversion to the `t_TO_TYPE`
371/// is not necessarily the same as conversion to `const t_TO_TYPE&`.
372///
373/// Note that significant documentation about the details of this
374/// implementation can be found in `bslmf_isconvertible.cpp`.
375template <class t_FROM_TYPE,
376 class t_TO_TYPE
377#if defined(BSLS_PLATFORM_CMP_GNU) || defined(BSLS_PLATFORM_CMP_CLANG)
378 ,
379 int IS_FROM_FUNDAMENTAL = bsl::is_fundamental<t_FROM_TYPE>::value,
380 int IS_TO_FUNDAMENTAL = bsl::is_fundamental<t_TO_TYPE>::value
381#endif
382 >
384
385 private:
386 /// A unique (empty) type returned by the comma operator.
387 struct Test
388 {
389
390 /// Return a reference to type `IsConvertible_Match`.
391 IsConvertible_Match& operator, (t_TO_TYPE) const;
392 };
393
394 public:
395
396#ifdef BSLS_PLATFORM_CMP_MSVC
397# pragma warning(push)
398# pragma warning(disable: 4244) // loss of precision warning ignored
399#endif
400 enum {
401
404 (Test(), TypeRep<t_FROM_TYPE>::rep()))))
405 // Return the convertibility between 't_FROM_TYPE' and 't_TO_TYPE'.
406 // This is set by invoking the 'operator,' method having 'Test&' on
407 // the left and 't_FROM_TYPE' on the right. The 'value' is 'true' if
408 // 't_FROM_TYPE' is convertible to 't_TO_TYPE', and 'false' otherwise.
409 };
410
411#ifdef BSLS_PLATFORM_CMP_MSVC
412# pragma warning(pop)
413#endif
414
415 /// This `typedef` returns `bsl::true_type` if `t_FROM_TYPE` is
416 /// convertible to `t_TO_TYPE`, and `bsl::false_type` otherwise.
418};
419
420#if 0 // defined(BSLS_PLATFORM_CMP_GNU) || defined(BSLS_PLATFORM_CMP_CLANG)
421// The following template partial specializations produce the same results as
422// the unspecialized template would, but avoid generating conversion warnings
423// on the affected compilers. However, there is one known bug in this block of
424// code (reported by the test driver, not yet tracked down) and experimentally
425// removing it seems to clear the bug, without raising the feared warnings on
426// supported gcc platforms - although it still raises a few warnings with gcc
427// 4.3.5.
428
429#define BSLMF_ISCONVERTIBLE_SAMETYPEVALUE(t_VALUE, \
430 t_FROM, \
431 t_TO, \
432 t_FROM_FUND, \
433 t_TO_FUND) \
434 template <class t_TYPE> \
435 struct IsConvertible_Imp<t_FROM, t_TO, t_FROM_FUND, t_TO_FUND> \
436 : bsl::integral_constant<bool, VALUE> { \
437 };
438 // This partial specialization of 'bslmf::IsConvertible_Imp' derives from
439 // 'bsl::integral_constant' having the specified macro argument 'VALUE'.
440 // The specified macro arguments 't_FROM' and 't_TO' are cv-qualified type
441 // expressions constructed out of the (template parameter) 't_TYPE'.
442
443#define BSLMF_ISCONVERTIBLE_VALUE(t_VALUE, \
444 t_FROM, \
445 t_TO, \
446 t_FROM_FUND, \
447 t_TO_FUND) \
448 template <class t_FROM_TYPE, class t_TO_TYPE> \
449 struct IsConvertible_Imp<t_FROM, t_TO, t_FROM_FUND, t_TO_FUND> \
450 : bsl::integral_constant<bool, t_VALUE> { \
451 };
452 // This partial specialization of 'bslmf::IsConvertible_Imp' derives from
453 // 'bsl::integral_constant' having the specified macro argument 't_VALUE'.
454 // The specified macro arguments 't_FROM' and 't_TO' are cv-qualified type
455 // expressions constructed out of 't_FROM_TYPE' and 't_TO_TYPE',
456 // respectively.
457
458#define BSLMF_ISCONVERTIBLE_FORWARD(t_FROM, t_TO, t_FROM_FUND, t_TO_FUND) \
459 template <class t_FROM_TYPE, class t_TO_TYPE> \
460 struct IsConvertible_Imp<t_FROM, t_TO, t_FROM_FUND, t_TO_FUND> \
461 : IsConvertible_Imp<t_FROM, t_TO, 0, 0> { \
462 };
463 // This partial specialization of 'bslmf::IsConvertible_Imp' applies the
464 // general mechanism for non-fundamental types. The specified macro
465 // arguments 't_FROM' and 't_TO' are cv-qualified type expressions
466 // constructed out of 't_FROM_TYPE' and 't_TO_TYPE', respectively.
467
468BSLMF_ISCONVERTIBLE_SAMETYPEVALUE(0,
469 const volatile t_TYPE,
470 const t_TYPE&,
471 1,
472 1)
473BSLMF_ISCONVERTIBLE_SAMETYPEVALUE(0,
474 volatile t_TYPE,
475 const t_TYPE&,
476 1,
477 1)
478 // These two partial specializations are instantiated when a (possibly
479 // 'const'-qualified) 'volatile' fundamental type is tested for
480 // convertibility to its 'const' reference type. The conversion shall
481 // fail.
482
483BSLMF_ISCONVERTIBLE_VALUE(1,
484 const volatile t_FROM_TYPE,
485 const t_TO_TYPE&,
486 1,
487 1)
488BSLMF_ISCONVERTIBLE_VALUE(1,
489 volatile t_FROM_TYPE,
490 const t_TO_TYPE&,
491 1,
492 1)
493 // These two partial specializations are instantiated when a (possibly
494 // 'const'-qualified) 'volatile' type is tested for convertibility to the
495 // 'const' reference type of another fundamental type. These partial
496 // specializations will be picked up if the previous two fail to match.
497 // The conversion shall succeed.
498
499BSLMF_ISCONVERTIBLE_VALUE(1, const t_FROM_TYPE, const t_TO_TYPE&, 1, 1)
500BSLMF_ISCONVERTIBLE_VALUE(1, t_FROM_TYPE, const t_TO_TYPE&, 1, 1)
501 // These two partial specializations are instantiated when a (possibly
502 // 'const'-qualified) fundamental type is tested for convertibility to the
503 // 'const' reference type of another fundamental type. These partial
504 // specializations will be picked up if the previous two fail to match.
505 // The conversion shall succeed.
506
507BSLMF_ISCONVERTIBLE_FORWARD(const volatile t_FROM_TYPE,
508 const volatile t_TO_TYPE&, 1, 1)
509BSLMF_ISCONVERTIBLE_FORWARD( volatile t_FROM_TYPE,
510 const volatile t_TO_TYPE&, 1, 1)
511BSLMF_ISCONVERTIBLE_FORWARD(const t_FROM_TYPE,
512 const volatile t_TO_TYPE&, 1, 1)
513BSLMF_ISCONVERTIBLE_FORWARD( t_FROM_TYPE,
514 const volatile t_TO_TYPE&, 1, 1)
515 // These four partial specializations are instantiated when a (possibly
516 // cv-qualified) fundamental type is tested for convertibility to the
517 // 'const volatile' reference type of another fundamental type.
518
519BSLMF_ISCONVERTIBLE_FORWARD(const volatile t_FROM_TYPE,
520 volatile t_TO_TYPE&, 1, 1)
521BSLMF_ISCONVERTIBLE_FORWARD( volatile t_FROM_TYPE,
522 volatile t_TO_TYPE&, 1, 1)
523BSLMF_ISCONVERTIBLE_FORWARD(const t_FROM_TYPE,
524 volatile t_TO_TYPE&, 1, 1)
525BSLMF_ISCONVERTIBLE_FORWARD( t_FROM_TYPE,
526 volatile t_TO_TYPE&, 1, 1)
527 // These four partial specializations are instantiated when a (possibly
528 // cv-qualified) fundamental type is tested for convertibility to the
529 // 'volatile' reference type of another fundamental type.
530
531BSLMF_ISCONVERTIBLE_FORWARD(const volatile t_FROM_TYPE, t_TO_TYPE&, 1, 1)
532BSLMF_ISCONVERTIBLE_FORWARD( volatile t_FROM_TYPE, t_TO_TYPE&, 1, 1)
533BSLMF_ISCONVERTIBLE_FORWARD(const t_FROM_TYPE, t_TO_TYPE&, 1, 1)
534BSLMF_ISCONVERTIBLE_FORWARD( t_FROM_TYPE, t_TO_TYPE&, 1, 1)
535 // These four partial specializations are instantiated when a (possibly
536 // cv-qualified) fundamental type is tested for convertibility to the
537 // non-cv-qualified reference type of another fundamental type.
538
539template <class t_FROM_TYPE, class t_TO_TYPE>
540struct IsConvertible_Imp<const t_FROM_TYPE, t_TO_TYPE, 1, 1>
541 : IsConvertible_Imp<const t_FROM_TYPE, double, 0, 0>::type {
542 // This partial specialization is instantiated when the 'const' (template
543 // parameter) fundamental 't_FROM_TYPE' is tested for convertibility to
544 // another (template parameter) fundamental 't_TO_TYPE'. This partial
545 // specialization derives from
546 // 'IsConvertible_Imp<const t_FROM_TYPE, double, 0, 0>' to avoid any
547 // compilation warnings in case the 't_TO_TYPE' is an integral type and
548 // 't_FROM_TYPE' is a floating-point type.
549};
550
551template <class t_FROM_TYPE, class t_TO_TYPE>
552struct IsConvertible_Imp<t_FROM_TYPE, t_TO_TYPE, 1, 1>
553 : IsConvertible_Imp<t_FROM_TYPE, double, 0, 0>::type {
554 // This partial specialization is instantiated when the (template
555 // parameter) fundamental 't_FROM_TYPE' is tested for convertibility to
556 // another (template parameter) fundamental 't_TO_TYPE'. This partial
557 // specialization derives from
558 // 'IsConvertible_Imp<t_FROM_TYPE, double, 0, 0>' to avoid any compilation
559 // warnings in case that the 't_FROM_TYPE' is a floating-point type and
560 // 't_TO_TYPE' is an integral type.
561};
562
563template <class t_FROM_TYPE, class t_TO_TYPE>
564struct IsConvertible_Imp<t_FROM_TYPE, t_TO_TYPE, 0, 1>
565 : IsConvertible_Imp<t_FROM_TYPE, double, 0, 0>::type {
566 // This partial specialization is instantiated when the (template
567 // parameter) 't_FROM_TYPE' is a non-fundamental type, and the (template
568 // parameter) 't_TO_TYPE' is a non-'void' fundamental type. This partial
569 // specialization derives from
570 // 'IsConvertible_Imp<t_FROM_TYPE, double, 0, 0>' to avoid any compilation
571 // warnings in case that the 't_FROM_TYPE' is a floating-point type and the
572 // 't_TO_TYPE' is an integral type.
573};
574
575template <class t_FROM_TYPE, class t_TO_TYPE>
576struct IsConvertible_Imp<t_FROM_TYPE, t_TO_TYPE, 1, 0>
577 : IsConvertible_Imp<int, t_TO_TYPE, 0, 0>::type {
578 // This partial specialization is instantiated when the (template
579 // parameter) 't_FROM_TYPE' is a non-'void' fundamental type, and the
580 // (template parameter) 't_TO_TYPE' is a non-fundamental type. This
581 // partial specialization derives from
582 // 'IsConvertible_Imp<int, t_TO_TYPE, 0, 0>' to avoid any compilation
583 // warnings in case that the 't_FROM_TYPE' is a floating-point type and the
584 // 't_TO_TYPE' is an integral type.
585};
586
587#undef BSLMF_ISCONVERTIBLE_SAMETYPEVALUE
588#undef BSLMF_ISCONVERTIBLE_VALUE
589#undef BSLMF_ISCONVERTIBLE_FORWARD
590
591#endif
592
593template <class t_TO_TYPE>
595: bsl::add_lvalue_reference<typename bsl::add_const<
596 typename bsl::remove_cv<t_TO_TYPE>::type>::type> {
597};
598
599template <class t_FROM_TYPE, class t_TO_TYPE>
602 bsl::is_void<t_FROM_TYPE>::value ||
603 bsl::is_array<t_TO_TYPE>::value ||
604 bsl::is_function<t_TO_TYPE>::value> {
605};
606
607template <class t_FROM_TYPE, class t_TO_TYPE>
610 IsConvertible_IsNeverConvertible<t_FROM_TYPE, t_TO_TYPE>::value,
611 bsl::false_type,
612 IsConvertible_Imp<t_FROM_TYPE,
613 typename IsConvertible_LazyTrait<t_TO_TYPE>::type> >::
614 type {
615};
616
617template <class t_FROM_TYPE, class t_TO_TYPE>
620 bsl::is_void<t_TO_TYPE>::value,
621 typename bsl::is_void<t_FROM_TYPE>::type,
622 IsConvertible_FilterNeverConvertible<
623 typename IsConvertible_CheckComplete<t_FROM_TYPE>::type,
624 typename IsConvertible_CheckComplete<t_TO_TYPE>::type> >::type {
625};
626
627} // close package namespace
628
629
630namespace bsl {
631
632 // ==============================
633 // struct is_convertible_dispatch
634 // ==============================
635
636/// This `struct` template implements the `is_convertible_dispatch`
637/// meta-function defined in the C++11 standard [meta.rel] to determine if
638/// the (template parameter) `t_FROM_TYPE` is convertible to the (template
639/// parameter) `t_TO_TYPE`. This `struct` derives from `bsl::true_type` if
640/// the `t_FROM_TYPE` is convertible to `t_TO_TYPE`, and from
641/// `bsl::false_type` otherwise. Note that both `t_FROM_TYPE` and
642/// `t_TO_TYPE` should be complete types, arrays of unknown bound, or
643/// (possibly cv-qualified) `void` types.
644template <class t_FROM_TYPE, class t_TO_TYPE>
646: BloombergLP::bslmf::IsConvertible_Conditional<t_FROM_TYPE, t_TO_TYPE>::type {
647};
648
649/// This set of rules corresponds with the reference binding rules in c++11,
650/// where the specification of `is_convertible_dispatch` relies on
651/// rvalue-references. We must supply these specializations directly in
652/// order to support C++03 compilers that do not have a good substitute for
653/// rvalue-references, as using `const &` instead produces subtly different
654/// results in some cases.
655template <class t_TYPE>
662
663// Some compilers need explicit guidance on a few of the reference-binding
664// conversions. All compilers get most of these correct, but once a few
665// specializations are added, the full set is required to avoid ambiguities.
666
667template <class t_TYPE>
668struct is_convertible_dispatch<t_TYPE, const t_TYPE&> : true_type {
669};
670
671template <class t_TYPE>
672struct is_convertible_dispatch<t_TYPE, volatile t_TYPE&> : false_type {
673};
674
675template <class t_TYPE>
676struct is_convertible_dispatch<t_TYPE, const volatile t_TYPE&> : false_type {
677};
678
679template <class t_TYPE>
680struct is_convertible_dispatch<const t_TYPE, t_TYPE&> : false_type {
681};
682
683template <class t_TYPE>
684struct is_convertible_dispatch<const t_TYPE, const t_TYPE&> : true_type {
685};
686
687template <class t_TYPE>
688struct is_convertible_dispatch<const t_TYPE, volatile t_TYPE&> : false_type {
689};
690
691template <class t_TYPE>
692struct is_convertible_dispatch<const t_TYPE, const volatile t_TYPE&>
693: false_type {
694};
695
696template <class t_TYPE>
697struct is_convertible_dispatch<volatile t_TYPE, t_TYPE&> : false_type {
698};
699
700template <class t_TYPE>
701struct is_convertible_dispatch<volatile t_TYPE, const t_TYPE&> : false_type {
702};
703
704template <class t_TYPE>
705struct is_convertible_dispatch<volatile t_TYPE, volatile t_TYPE&>
706: false_type {
707};
708
709template <class t_TYPE>
710struct is_convertible_dispatch<volatile t_TYPE, const volatile t_TYPE&>
711: false_type {
712};
713
714template <class t_TYPE>
715struct is_convertible_dispatch<const volatile t_TYPE, t_TYPE&> : false_type {
716};
717
718template <class t_TYPE>
719struct is_convertible_dispatch<const volatile t_TYPE, const t_TYPE&>
720: false_type {
721};
722
723template <class t_TYPE>
724struct is_convertible_dispatch<const volatile t_TYPE, volatile t_TYPE&>
725: false_type {
726};
727
728template <class t_TYPE>
729struct is_convertible_dispatch<const volatile t_TYPE, const volatile t_TYPE&>
730: false_type {
731};
732
733// The next group of partial specializations deal with various cases of
734// converting to an lvalue-reference, which we make explicitly conform to the
735// C++11 idiom of converting from an rvalue (which may be an lvalue-reference).
736
737template <class t_TYPE>
738struct is_convertible_dispatch<t_TYPE&, t_TYPE&> : true_type {
739};
740
741template <class t_TYPE>
742struct is_convertible_dispatch<t_TYPE&, const t_TYPE&> : true_type {
743};
744
745template <class t_TYPE>
746struct is_convertible_dispatch<t_TYPE&, volatile t_TYPE&> : true_type {
747};
748
749template <class t_TYPE>
750struct is_convertible_dispatch<t_TYPE&, const volatile t_TYPE&> : true_type {
751};
752
753template <class t_TYPE>
754struct is_convertible_dispatch<const t_TYPE&, t_TYPE&> : false_type {
755};
756
757template <class t_TYPE>
758struct is_convertible_dispatch<const t_TYPE&, const t_TYPE&> : true_type {
759};
760
761template <class t_TYPE>
762struct is_convertible_dispatch<const t_TYPE&, volatile t_TYPE&> : false_type {
763};
764
765template <class t_TYPE>
766struct is_convertible_dispatch<const t_TYPE&, const volatile t_TYPE&>
767: true_type {
768};
769
770template <class t_TYPE>
771struct is_convertible_dispatch<volatile t_TYPE&, t_TYPE&> : false_type {
772};
773
774template <class t_TYPE>
775struct is_convertible_dispatch<volatile t_TYPE&, const t_TYPE&> : false_type {
776};
777
778template <class t_TYPE>
779struct is_convertible_dispatch<volatile t_TYPE&, volatile t_TYPE&>
780: true_type {
781};
782
783template <class t_TYPE>
784struct is_convertible_dispatch<volatile t_TYPE&, const volatile t_TYPE&>
785: true_type {
786};
787
788template <class t_TYPE>
789struct is_convertible_dispatch<const volatile t_TYPE&, t_TYPE&> : false_type {
790};
791
792template <class t_TYPE>
793struct is_convertible_dispatch<const volatile t_TYPE&, const t_TYPE&>
794: false_type {
795};
796
797template <class t_TYPE>
798struct is_convertible_dispatch<const volatile t_TYPE&, volatile t_TYPE&>
799: false_type {
800};
801
802template <class t_TYPE>
803struct is_convertible_dispatch<const volatile t_TYPE&, const volatile t_TYPE&>
804: true_type {
805};
806
807/// Correct handling of non-fundamental volatile conversions to self. Note
808/// that this is not trivially true, but tests that `t_TYPE` is copy (or
809/// move) constructible.
810template <class t_TYPE>
811struct is_convertible_dispatch<volatile t_TYPE, t_TYPE>
812: BloombergLP::bslmf::IsConvertible_Conditional<t_TYPE, t_TYPE>::type {
813};
814
815template <class t_FROM_TYPE, class t_TO_TYPE>
816struct is_convertible_dispatch<t_FROM_TYPE, volatile t_TO_TYPE&> : false_type {
817};
818
819template <class t_FROM_TYPE, class t_TO_TYPE>
820struct is_convertible_dispatch<t_FROM_TYPE, const volatile t_TO_TYPE&>
821: false_type {
822};
823
824template <class t_FROM_TYPE, class t_TO_TYPE>
825struct is_convertible_dispatch<volatile t_FROM_TYPE&, volatile t_TO_TYPE&>
827};
828
829template <class t_FROM_TYPE, class t_TO_TYPE>
830struct is_convertible_dispatch<volatile t_FROM_TYPE&,
831 const volatile t_TO_TYPE&>
833};
834
835 // =====================
836 // struct is_convertible
837 // =====================
838
839template <class t_FROM_TYPE>
840struct EffectiveFromType : conditional<is_fundamental<t_FROM_TYPE>::value ||
841 is_pointer<t_FROM_TYPE>::value,
842 typename remove_cv<t_FROM_TYPE>::type,
843 t_FROM_TYPE> {
844};
845
846template <class t_FROM_TYPE, class t_TO_TYPE>
847struct is_convertible_dispatch<volatile t_FROM_TYPE&, t_TO_TYPE>
851 typename BloombergLP::bslmf::IsConvertible_Conditional<
852 volatile t_FROM_TYPE,
853 t_TO_TYPE>::type>::type {
854};
855
856/// This `struct` template implements the `is_convertible_dispatch`
857/// meta-function defined in the C++11 standard [meta.rel] to determine if
858/// the (template parameter) `t_FROM_TYPE` is convertible to the (template
859/// parameter) `t_TO_TYPE`. This `struct` derives from `bsl::true_type` if
860/// the `t_FROM_TYPE` is convertible to `t_TO_TYPE`, and from
861/// `bsl::false_type` otherwise. Note that both `t_FROM_TYPE` and
862/// `t_TO_TYPE` should be complete types, arrays of unknown bound, or
863/// (possibly cv-qualified) `void` types.
864template <class t_FROM_TYPE, class t_TO_TYPE>
866: is_convertible_dispatch<typename EffectiveFromType<t_FROM_TYPE>::type,
867 t_TO_TYPE>::type {
868};
869
870} // close namespace bsl
871#endif
872
873
874namespace bslmf {
875
876 // ====================
877 // struct IsConvertible
878 // ====================
879
880/// This `struct` template implements a meta-function to determine if the
881/// (template parameter) `t_FROM_TYPE` is convertible to the (template
882/// parameter) `t_TO_TYPE`. This `struct` derives from `bsl::true_type` if
883/// the `t_FROM_TYPE` is convertible to `t_TO_TYPE`, and from
884/// `bsl::false_type` otherwise. Note that both `t_FROM_TYPE` and
885/// `t_TO_TYPE` should be complete types, arrays of unknown bound, or
886/// (possibly cv-qualified) `void` types.
887template <class t_FROM_TYPE, class t_TO_TYPE>
888struct IsConvertible : bsl::is_convertible<t_FROM_TYPE, t_TO_TYPE>::type {
889};
890
891} // close package namespace
892
893#ifndef BDE_OPENSOURCE_PUBLICATION // BACKWARD_COMPATIBILITY
894// ============================================================================
895// BACKWARD COMPATIBILITY
896// ============================================================================
897
898#ifdef bslmf_IsConvertible
899#undef bslmf_IsConvertible
900#endif
901/// This alias is defined for backward compatibility.
902#define bslmf_IsConvertible bslmf::IsConvertible
903#endif // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY
904
905
906
907#endif // ! defined(INCLUDED_BSLMF_ISCONVERTIBLE)
908
909// ----------------------------------------------------------------------------
910// Copyright 2013 Bloomberg Finance L.P.
911//
912// Licensed under the Apache License, Version 2.0 (the "License");
913// you may not use this file except in compliance with the License.
914// You may obtain a copy of the License at
915//
916// http://www.apache.org/licenses/LICENSE-2.0
917//
918// Unless required by applicable law or agreed to in writing, software
919// distributed under the License is distributed on an "AS IS" BASIS,
920// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
921// See the License for the specific language governing permissions and
922// limitations under the License.
923// ----------------------------- END-OF-FILE ----------------------------------
924
925/** @} */
926/** @} */
927/** @} */
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_KEYWORD_INLINE_VARIABLE
Definition bsls_keyword.h:623
Definition bdlb_printmethods.h:283
Definition bdlbb_blob.h:576
Definition bslmf_isconvertible.h:843
Definition bslmf_addlvaluereference.h:126
Definition bslmf_conditional.h:120
Definition bslmf_enableif.h:525
Definition bslmf_integralconstant.h:244
Definition bslmf_isconst.h:144
Definition bslmf_isconvertible.h:646
Definition bslmf_isconvertible.h:867
Definition bslmf_isfunction.h:232
Definition bslmf_isfundamental.h:329
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:624
Definition bslmf_isconvertible.h:614
Definition bslmf_isconvertible.h:383
@ value
Definition bslmf_isconvertible.h:402
bsl::integral_constant< bool, value > type
Definition bslmf_isconvertible.h:417
Definition bslmf_isconvertible.h:604
Definition bslmf_isconvertible.h:596
Definition bslmf_isconvertible.h:334
Definition bslmf_isconvertible.h:333
char a
Definition bslmf_isconvertible.h:333
Definition bslmf_isconvertible.h:331
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:888
Generate a reference to t_TYPE for use in meta-functions.
Definition bslmf_matchanytype.h:189