Type traits
Type traits in conjunction with enable_if
are turning into a required foundation for writing
template classes. Consider std::filesystem::path
: this has overloads that require help in order
for the compiler to disambiguate some of the required constructors and operators.
Let’s start with an interesting base, integral_constant
. This turns a constant into a type,
which means that templates can use it to control which template gets instantiated.
A modern version might look like this:
The bool_constant
specialization is provided as of C++17. However, except for the modern syntax
(e.g. using
instead of typedef
), this template is basic C++.
The entire reason for this is the side effects; otherwise, it’s a very expensive (in lines of code) way to represent a constant.
Starting with the most simple usage, we have two unique types true_type
and false_type
that are
specializations of bool_constant
, itself a specialization of integral_constant
. We can do
tag dispatching to select between two options at compile time. Let’s say we have a print function and
we want integer and floating point versions
Here, is_integral
is a type trait that inherits from bool_constant
and returns true_type
if
we have a type that is integral, e.g. int
, short
, etc. We could use normal overloading, but the promotion
rules often defeat our attempts at overloading.
Of course, as you see, we almost never use true_type
and false_type
directly. Instead, they are the
base type for type traits.
void_t
C++17 has void_t
:
and this is simply:
with the example being
where is_iterable
is a type trait and has a true
value if type T
is an iterable type, determined
by the fact that
An earlier version was proposed in: