type_traits
Introduction
The type_traits define compile-time template based interfaces to query the properties of types. The type_traits provides template functions and template structs that gives the ability to inspect and transform the properties of types.
For example, considering a generic type T, which may be an integer, boolean, or any other type, With type traits it is possible to query the compiler about the nature of T, such as determining if it is an integer or a pointer, among other properties. This functionality is particularly beneficial in conditional compilation, allowing the compiler to select the appropriate execution path based on the input type.
The type_traits can also apply some transformation to a type. For example, given T, you can add/remove the const specifier, the reference or the pointer and many other transformations.
Usage
The usage constraints and guidelines apply for type_traits:
Constraints |
Apply type_traits only for the compatible type. |
Usage guidance |
This is designed for scenarios where decisions are made to perform actions based on the properties of types during compilation. Use type traits to check properties of types before applying operations. Use type traits whenever there is a need in transformation of one type to another type. |
Example
The following examples provides an overview of usage of different type traits:
union tempU
{};
struct tempA
{};
struct tempB
{};
struct tempC : public tempB
{};
struct Call0
{
void operator()() {}
};
struct Call1
{
int operator()() { return 9; }
int operator()(int) { return 9; }
int operator()(int, int) { return 9; }
};
The following code shows that estd::is_class provides the member constant value which is equal to true, if T is a class type (but not union). Otherwise, value is equal to false:
ESTD_STATIC_ASSERT(::estd::is_class<Call0>::value);
ESTD_STATIC_ASSERT(::estd::is_class<Call1>::value);
ESTD_STATIC_ASSERT(::estd::is_class<tempA>::value);
ESTD_STATIC_ASSERT(::estd::is_class<tempC>::value);
The next piece of code shows that is_callable checks whether the given type is callable or not:
ESTD_STATIC_ASSERT(::estd::is_callable<Call0>::value);
ESTD_STATIC_ASSERT(::estd::is_callable<Call1>::value);
ESTD_STATIC_ASSERT(::estd::is_callable<void (*)()>::value);
ESTD_STATIC_ASSERT(!::estd::is_callable<tempA>::value);
ESTD_STATIC_ASSERT(!::estd::is_callable<tempC>::value);
ESTD_STATIC_ASSERT(!::estd::is_callable<int>::value);
The following code shows that estd::is_signed provides the member constant value which is equal to true for the floating-point types and the signed integer types. Otherwise, false for the unsigned integer types and the type bool:
ESTD_STATIC_ASSERT((::estd::is_same<bool, ::estd::make_signed<bool>::type>::value));
ESTD_STATIC_ASSERT((::estd::is_same<int8_t, ::estd::make_signed<int8_t>::type>::value));
ESTD_STATIC_ASSERT((::estd::is_same<int8_t, ::estd::make_signed<uint8_t>::type>::value));
ESTD_STATIC_ASSERT((::estd::is_same<int16_t, ::estd::make_signed<int16_t>::type>::value));
ESTD_STATIC_ASSERT((::estd::is_same<int16_t, ::estd::make_signed<uint16_t>::type>::value));
ESTD_STATIC_ASSERT((::estd::is_same<int32_t, ::estd::make_signed<int32_t>::type>::value));
ESTD_STATIC_ASSERT((::estd::is_same<int32_t, ::estd::make_signed<uint32_t>::type>::value));
ESTD_STATIC_ASSERT((::estd::is_same<int64_t, ::estd::make_signed<int64_t>::type>::value));
ESTD_STATIC_ASSERT((::estd::is_same<int64_t, ::estd::make_signed<uint64_t>::type>::value));
ESTD_STATIC_ASSERT((::estd::is_same<tempA, ::estd::make_signed<tempA>::type>::value));
The next piece of code shows that estd::is_base_of checks if a class is derived from another:
ESTD_STATIC_ASSERT((::estd::is_base_of<tempB, tempC>::value));
ESTD_STATIC_ASSERT(!(::estd::is_base_of<tempC, tempB>::value));
ESTD_STATIC_ASSERT((::estd::is_base_of<tempB, tempB>::value));
ESTD_STATIC_ASSERT(!(::estd::is_base_of<tempB, tempA>::value));
The following code shows that make_signed makes the given integral type signed:
ESTD_STATIC_ASSERT((::estd::is_same<bool, ::estd::make_signed<bool>::type>::value));
ESTD_STATIC_ASSERT((::estd::is_same<int8_t, ::estd::make_signed<int8_t>::type>::value));
ESTD_STATIC_ASSERT((::estd::is_same<int8_t, ::estd::make_signed<uint8_t>::type>::value));
ESTD_STATIC_ASSERT((::estd::is_same<int16_t, ::estd::make_signed<int16_t>::type>::value));
ESTD_STATIC_ASSERT((::estd::is_same<int16_t, ::estd::make_signed<uint16_t>::type>::value));
ESTD_STATIC_ASSERT((::estd::is_same<int32_t, ::estd::make_signed<int32_t>::type>::value));
ESTD_STATIC_ASSERT((::estd::is_same<int32_t, ::estd::make_signed<uint32_t>::type>::value));
ESTD_STATIC_ASSERT((::estd::is_same<int64_t, ::estd::make_signed<int64_t>::type>::value));
ESTD_STATIC_ASSERT((::estd::is_same<int64_t, ::estd::make_signed<uint64_t>::type>::value));
ESTD_STATIC_ASSERT((::estd::is_same<tempA, ::estd::make_signed<tempA>::type>::value));