Boost.Hana  1.7.1
Your standard library for metaprogramming
boost::hana::integral_constant< T, v > Struct Template Reference

Description

template<typename T, T v>
struct boost::hana::integral_constant< T, v >

Compile-time value of an integral type.

An integral_constant is an object that represents a compile-time integral value. As the name suggests, hana::integral_constant is basically equivalent to std::integral_constant, except that hana::integral_constant also provide other goodies to make them easier to use, like arithmetic operators and similar features. In particular, hana::integral_constant is guaranteed to inherit from the corresponding std::integral_constant, and hence have the same members and capabilities. The sections below explain the extensions to std::integral_constant provided by hana::integral_constant.

Arithmetic operators

hana::integral_constant provides arithmetic operators that return hana::integral_constants to ease writing compile-time arithmetic:

BOOST_HANA_CONSTANT_CHECK(hana::int_c<1> + hana::int_c<3> == hana::int_c<4>);
// Mixed-type operations are supported, but only when it involves a
// promotion, and not a conversion that could be lossy.
BOOST_HANA_CONSTANT_CHECK(hana::size_c<3> * hana::ushort_c<5> == hana::size_c<15>);
BOOST_HANA_CONSTANT_CHECK(hana::llong_c<15> == hana::int_c<15>);
#define BOOST_HANA_CONSTANT_CHECK(...)
Equivalent to BOOST_HANA_CONSTANT_ASSERT, but not influenced by the BOOST_HANA_CONFIG_DISABLE_ASSERTI...
Definition: assert.hpp:239

It is pretty important to realize that these operators return other integral_constants, not normal values of an integral type. Actually, all those operators work pretty much in the same way. Simply put, for an operator @,

integral_constant<T, x>{} @ integral_constant<T, y>{} == integral_constant<T, x @ y>{}

The fact that the operators return Constants is very important because it allows all the information that's known at compile-time to be conserved as long as it's only used with other values known at compile-time. It is also interesting to observe that whenever an integral_constant is combined with a normal runtime value, the result will be a runtime value (because of the implicit conversion). In general, this gives us the following table

left operand right operand result
integral_constant integral_constant integral_constant
integral_constant runtime runtime
runtime integral_constant runtime
runtime runtime runtime

The full range of provided operators is

  • Arithmetic: binary +, binary -, /, *, %, unary +, unary -
  • Bitwise: ~, &, |, ^, <<, >>
  • Comparison: ==, !=, <, <=, >, >=
  • Logical: ||, &&, !

Construction with user-defined literals

integral_constants of type long long can be created with the _c user-defined literal, which is contained in the literals namespace:

using namespace hana::literals; // contains the _c suffix
BOOST_HANA_CONSTANT_CHECK(1234_c == hana::llong_c<1234>);
BOOST_HANA_CONSTANT_CHECK(-1234_c == hana::llong_c<-1234>);
BOOST_HANA_CONSTANT_CHECK(1_c + (3_c * 4_c) == hana::llong_c<1 + (3 * 4)>);

Modeled concepts

  1. Constant and IntegralConstant
    An integral_constant is a model of the IntegralConstant concept in the most obvious way possible. Specifically,
    constexpr auto value
    Return the compile-time value associated to a constant.
    Definition: value.hpp:54
    The model of Constant follows naturally from the model of IntegralConstant, i.e.
    value<integral_constant<T, v>>() == v // of type T
  2. Comparable, Orderable, Logical, Monoid, Group, Ring, and EuclideanRing, Hashable
    Those models are exactly those provided for Constants, which are documented in their respective concepts.

Synopsis of associated functions

template<typename T , T v>
constexpr integral_constant< T, v > integral_c {}
 Creates an integral_constant holding the given compile-time value. More...
 
template<char ... c>
constexpr auto operator""_c ()
 Creates a hana::integral_constant from a literal. More...
 

Friends

template<typename X , typename Y >
constexpr friend auto operator+ (X &&x, Y &&y)
 Equivalent to hana::plus
 
template<typename X , typename Y >
constexpr friend auto operator- (X &&x, Y &&y)
 Equivalent to hana::minus
 
template<typename X >
constexpr friend auto operator- (X &&x)
 Equivalent to hana::negate
 
template<typename X , typename Y >
constexpr friend auto operator* (X &&x, Y &&y)
 Equivalent to hana::mult
 
template<typename X , typename Y >
constexpr friend auto operator/ (X &&x, Y &&y)
 Equivalent to hana::div
 
template<typename X , typename Y >
constexpr friend auto operator% (X &&x, Y &&y)
 Equivalent to hana::mod
 
template<typename X , typename Y >
constexpr friend auto operator== (X &&x, Y &&y)
 Equivalent to hana::equal
 
template<typename X , typename Y >
constexpr friend auto operator!= (X &&x, Y &&y)
 Equivalent to hana::not_equal
 
template<typename X , typename Y >
constexpr friend auto operator|| (X &&x, Y &&y)
 Equivalent to hana::or_
 
template<typename X , typename Y >
constexpr friend auto operator&& (X &&x, Y &&y)
 Equivalent to hana::and_
 
template<typename X >
constexpr friend auto operator! (X &&x)
 Equivalent to hana::not_
 
template<typename X , typename Y >
constexpr friend auto operator< (X &&x, Y &&y)
 Equivalent to hana::less
 
template<typename X , typename Y >
constexpr friend auto operator> (X &&x, Y &&y)
 Equivalent to hana::greater
 
template<typename X , typename Y >
constexpr friend auto operator<= (X &&x, Y &&y)
 Equivalent to hana::less_equal
 
template<typename X , typename Y >
constexpr friend auto operator>= (X &&x, Y &&y)
 Equivalent to hana::greater_equal
 

Static Public Member Functions

template<typename F >
static constexpr void times (F &&f)
 Call a function n times. More...
 

Associated functions

◆ integral_c

template<typename T , T v>
template<typename T , T v>
constexpr integral_constant<T, v> integral_c {}
related

Creates an integral_constant holding the given compile-time value.

Specifically, integral_c<T, v> is a hana::integral_constant holding the compile-time value v of an integral type T.

Template Parameters
TThe type of the value to hold in the integral_constant. It must be an integral type.
vThe integral value to hold in the integral_constant.

Example

BOOST_HANA_CONSTANT_CHECK(hana::integral_c<int, 2> == hana::int_c<2>);
static_assert(decltype(hana::integral_c<int, 2>)::value == 2, "");

◆ operator""_c()

template<char ... c>
constexpr auto operator""_c ( )
related

Creates a hana::integral_constant from a literal.

The literal is parsed at compile-time and the result is returned as a llong<...>.

Note
We use llong<...> instead of ullong<...> because using an unsigned type leads to unexpected behavior when doing stuff like -1_c. If we used an unsigned type, -1_c would be something like ullong<-1> which is actually ullong<something huge>.

Example

using namespace hana::literals; // contains the _c suffix
BOOST_HANA_CONSTANT_CHECK(1234_c == hana::llong_c<1234>);
BOOST_HANA_CONSTANT_CHECK(-1234_c == hana::llong_c<-1234>);
BOOST_HANA_CONSTANT_CHECK(1_c + (3_c * 4_c) == hana::llong_c<1 + (3 * 4)>);

Member Function Documentation

◆ times()

template<typename T , T v>
template<typename F >
static constexpr void boost::hana::integral_constant< T, v >::times ( F &&  f)
staticconstexpr

Call a function n times.

times allows a nullary function to be invoked n times:

static constexpr void times(F &&f)
Call a function n times.
Definition: integral_constant.hpp:168

should be expanded by any decent compiler to

f(); f(); f();

This can be useful in several contexts, e.g. for loop unrolling:

std::string s;
for (char c = 'x'; c <= 'z'; ++c)
hana::int_<5>::times([&] { s += c; });
BOOST_HANA_RUNTIME_CHECK(s == "xxxxxyyyyyzzzzz");
#define BOOST_HANA_RUNTIME_CHECK(...)
Equivalent to BOOST_HANA_RUNTIME_ASSERT, but not influenced by the BOOST_HANA_CONFIG_DISABLE_ASSERTIO...
Definition: assert.hpp:209

Note that times is really a static function object, not just a static function. This allows int_<n>::times to be passed to higher-order algorithms:

std::string s;
auto functions = hana::make_tuple(
[&] { s += "x"; },
[&] { s += "y"; },
[&] { s += "z"; }
);
hana::for_each(functions, hana::int_<5>::times);
BOOST_HANA_RUNTIME_CHECK(s == "xxxxxyyyyyzzzzz");
constexpr auto for_each
Perform an action on each element of a foldable, discarding the result each time.
Definition: for_each.hpp:39

Also, since static members can be accessed using both the . and the :: syntax, one can take advantage of this (loophole?) to call times on objects just as well as on types:

std::string s;
for (char c = 'x'; c <= 'z'; ++c)
hana::int_c<5>.times([&] { s += c; });
BOOST_HANA_RUNTIME_CHECK(s == "xxxxxyyyyyzzzzz");
Note
times is equivalent to the hana::repeat function, which works on an arbitrary IntegralConstant.

Sometimes, it is also useful to know the index we're at inside the function. This can be achieved by using times.with_index:

std::vector<int> v;
hana::int_<5>::times.with_index([&](auto index) { v.push_back(index); });
BOOST_HANA_RUNTIME_CHECK(v == std::vector<int>{0, 1, 2, 3, 4});

Remember that times is a function object, and hence it can have subobjects. with_index is just a function object nested inside times, which allows for this nice little interface. Also note that the indices passed to the function are integral_constants; they are known at compile-time. Hence, we can do compile-time stuff with them, like indexing inside a tuple:

constexpr auto xs = hana::tuple_c<int, 0, 1, 2>;
hana::int_<3>::times.with_index([xs](auto index) {
BOOST_HANA_CONSTANT_CHECK(xs[index] == index);
});
Note
times.with_index(f) guarantees that the calls to f will be done in order of ascending index. In other words, f will be called as f(0), f(1), f(2), etc., but with integral_constants instead of normal integers. Side effects can also be done in the function passed to times and times.with_index.