I'm just into metaprogramming and was watching Cppcon channel on youtube, and saw this std::integral_constant
, but cannot find its use.
As far as i understood, it is a way to "pack" a value along with its type, it can be instantiated with
std::integral_constant<int, 42> i;
std::integral_constant<bool, true> b;
std::integral_constant<float, 3.14> f;
...
and each of those instances can be used just like the value they contains, i.e.: can be passed around, used in math operations, comparisons, etc.
But i cannot understand why should i use those structs instead of the actual contained values, nor if i can actually access the value type (i.e.: int
, bool
and float
) at runtime to do stuff with it.
Can someone present a simple example of practical use of this feature? An example that explain its usage difference from using the actual values?
std::integral_constant
is mainly used as a utility type for writing meta-programming traits, particularly by encoding a type with a type and a value. By letting a custom trait inherit from specializations of std::integral_constant
we get easy, idiomatic access to a stored non-type template parameter through the static member constant value
, as well as e.g. the value type of this constant via the member typedef value_type
.
std::integral_constant
could be used for, say, writing a dimensionality trait for a matrix type
using index_t = int;
template <index_t M, index_t N, typename S> struct mat {
// matrix implementation
};
as
#include <type_traits>
// Default dimensionality 0.
template <class T, typename = void>
struct dimensionality : std::integral_constant<index_t, 0> {};
template <typename S>
struct dimensionality<S, std::enable_if_t<std::is_arithmetic_v<S>>>
: std::integral_constant<index_t, 1> {};
template <index_t M, index_t N, typename S>
struct dimensionality<mat<M, N, S>> : std::integral_constant<index_t, M * N> {};
template <class T>
inline constexpr index_t dimensionality_v = dimensionality<T>::value;
DEMO.
However, a more common use case is to use the two helper typedefs std::true_type
and std::false_type
for the common case where T
is bool
.
Type Definition ---- ---------- true_type std::integral_constant<bool, true> false_type std::integral_constant<bool, false>
E.g. as
#include <type_traits>
struct Foo {};
template <typename T>
struct is_foo : public std::false_type {};
template<>
struct is_foo<Foo> : public std::true_type {};
template<typename T>
constexpr bool is_foo_v = is_foo<T>::value;
static_assert(is_foo_v<Foo>, "");
static_assert(!is_foo_v<int>, "");
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With