BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslmf_isconvertible

Macros

#define bslmf_IsConvertible   bslmf::IsConvertible
 This alias is defined for backward compatibility.
 

Detailed Description

Outline

Purpose

Provide a compile-time check for type conversion.

Classes

See also
bslmf_integralconstant

Description

This component defines two meta-functions, bsl::is_convertible and BloombergLP::bslmf::IsConvertible and a template variable bsl::is_convertible_v, that represents the result value of the bsl::is_convertible meta-function. All these meta-functions may be used to check whether an implicit conversion exists from one type to another.

When compiling on C++11 or later, both meta-functions are aliases to the standard library implementation std::is_convertible.

When compiling on C++03 bsl::is_convertible tries to meet the requirements of the is_convertible template defined in the C++11 standard [meta.rel] as much as possible but fails in some corner cases. One example of such a case:

class A {};
class B { public: B(A& ); };
BSLMF_ASSERT((!bsl::is_convertible<A, B>::value)); //<-- FAIL in C++03 mode
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:229
Definition bslmf_isconvertible.h:867

bslmf::IsConvertible was devised before is_convertible was standardized and is functionally equivalent except that bsl::is_convertible does not allow its template parameter types to be incomplete types according to the C++11 standard while bslmf::IsConvertible tests conversions involving incomplete types.

Note that bsl::is_convertible should be preferred over bslmf::IsConvertible, and in general, should be used by new components. Also note that bsl::is_convertible and bslmf::IsConvertible can produce compiler errors if the conversion is ambiguous. For example:

struct A {};
struct B : public A {};
struct C : public A {};
struct D : public B, public C {};
static int const C = bsl::is_convertible<D*, A*>::value; // ERROR!

Also note that the template variable is_convertible_v is defined in the C++17 standard as an inline variable. If the current compiler supports the inline variable C++17 compiler feature, bsl::is_convertible_v is defined as an inline constexpr bool variable. Otherwise, if the compiler supports the variable templates C++14 compiler feature, bsl::is_convertible_v is defined as a non-inline constexpr bool variable. See BSLS_COMPILERFEATURES_SUPPORT_INLINE_VARIABLES and BSLS_COMPILERFEATURES_SUPPORT_VARIABLE_TEMPLATES macros in bsls_compilerfeatures component for details.

Usage

In this section we show intended use of this component.

Example 1: Select Function Based on Type Convertibility

The bsl::is_convertible meta-function can be used to select an appropriate function (at compile time) based on the convertibility of one type to another without causing a compiler error by actually trying the conversion.

First, we define two classes, Foo and Bar. The Foo class has an explict constructor from int, an implicit conversion operator that returns an integer value while the Bar class does neither:

class Foo {
// DATA
int d_value;
public:
// CREATORS
explicit Foo(int value) : d_value(value) {}
// ACCESSORS
operator int() const { return d_value; }
};
class Bar {};

Then, we run:

Note that int to Foo is false, even though Foo has a constructor that takes an int. This is because that constructor is explicit, and is_converitble ignores explicit constructors.

Next, we go on to demonstrate how this could be used. Suppose we are implementing a convertToInt template method that converts a given object of the (template parameter) t_TYPE to int type, and returns the integer value. If the given object can not convert to int, return 0. The method calls an overloaded function, getIntValue, to get the converted integer value. The idea is to invoke one version of getIntValue if the type provides a conversion operator that returns an integer value, and another version if the type does not provide such an operator.

We define the first getIntValue function that takes a bsl::false_type as its last argument, whereas the second getIntValue function takes a bsl::true_type object. The result of the bsl::is_convertible meta-function (i.e., its type member) is used to create the last argument passed to getIntValue. Neither version of getIntValue makes use of this argument – it is used only to differentiate the argument list so we can overload the function.

template <class t_TYPE>
inline
int getIntValue(t_TYPE *, bsl::false_type)
{
// Return 0 because the specified 't_TYPE' is not convertible to the
// 'int' type.
return 0;
}
template <class t_TYPE>
inline
int getIntValue(t_TYPE *object, bsl::true_type)
{
// Return the integer value converted from the specified 'object' of
// the (template parameter) 't_TYPE'.
return int(*object);
}
Definition bslmf_integralconstant.h:244

Now, we define our convertToInt method:

template <class t_TYPE>
inline
int convertToInt(t_TYPE *object)
{
typedef typename bsl::is_convertible<t_TYPE,
int>::type CanConvertToInt;
return getIntValue(object, CanConvertToInt());
}

Notice that we use bsl::is_convertible to get a bsl::false_type or bsl::true_type, and then call the corresponding overloaded getIntValue method.

Finally, we call our finished product and observe the return values:

Foo foo(99);
Bar bar;
assert(99 == convertToInt(&foo));
assert(0 == convertToInt(&bar));

Macro Definition Documentation

◆ bslmf_IsConvertible

#define bslmf_IsConvertible   bslmf::IsConvertible