Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++20 std::integral_constant?

Tags:

c++

std

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?

like image 540
fudo Avatar asked Oct 11 '20 09:10

fudo


1 Answers

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.


Examples

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>, "");
like image 99
dfrib Avatar answered Oct 10 '22 22:10

dfrib