Boost.Hana  1.0.2
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>);

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, 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<bool b>
using bool_ = integral_constant< bool, b >
 
using true_ = bool_< true >
 
using false_ = bool_< false >
 
template<char c>
using char_ = integral_constant< char, c >
 
template<short i>
using short_ = integral_constant< short, i >
 
template<unsigned short i>
using ushort_ = integral_constant< unsigned short, i >
 
template<int i>
using int_ = integral_constant< int, i >
 
template<unsigned int i>
using uint = integral_constant< unsigned int, i >
 
template<long i>
using long_ = integral_constant< long, i >
 
template<unsigned long i>
using ulong = integral_constant< unsigned long, i >
 
template<long long i>
using llong = integral_constant< long long, i >
 
template<unsigned long long i>
using ullong = integral_constant< unsigned long long, i >
 
template<std::size_t i>
using size_t = integral_constant< std::size_t, i >
 
template<typename T , T v>
constexpr integral_constant< T, v > integral_c {}
 Creates an integral_constant holding the given compile-time value. More...
 
template<bool b>
constexpr bool_< b > bool_c {}
 
constexpr auto true_c = bool_c<true>
 
constexpr auto false_c = bool_c<false>
 
template<char c>
constexpr char_< c > char_c {}
 
template<short i>
constexpr short_< i > short_c {}
 
template<unsigned short i>
constexpr ushort_< i > ushort_c {}
 
template<int i>
constexpr int_< i > int_c {}
 
template<unsigned int i>
constexpr uint< i > uint_c {}
 
template<long i>
constexpr long_< i > long_c {}
 
template<unsigned long i>
constexpr ulong< i > ulong_c {}
 
template<long long i>
constexpr llong< i > llong_c {}
 
template<unsigned long long i>
constexpr ullong< i > ullong_c {}
 
template<std::size_t i>
constexpr size_t< i > size_c {}
 
template<char... c>
constexpr auto operator""_c ()
 Creates a hana::integral_constant from a literal. More...
 

Friends

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

template<typename T, T v>
template<bool b>
using bool_ = integral_constant<bool, b>
related
template<typename T, T v>
using true_ = bool_<true>
related
template<typename T, T v>
using false_ = bool_<false>
related
template<typename T, T v>
template<char c>
using char_ = integral_constant<char, c>
related
template<typename T, T v>
template<short i>
using short_ = integral_constant<short, i>
related
template<typename T, T v>
template<unsigned short i>
using ushort_ = integral_constant<unsigned short, i>
related
template<typename T, T v>
template<int i>
using int_ = integral_constant<int, i>
related
template<typename T, T v>
template<unsigned int i>
using uint = integral_constant<unsigned int, i>
related
template<typename T, T v>
template<long i>
using long_ = integral_constant<long, i>
related
template<typename T, T v>
template<unsigned long i>
using ulong = integral_constant<unsigned long, i>
related
template<typename T, T v>
template<long long i>
using llong = integral_constant<long long, i>
related
template<typename T, T v>
template<unsigned long long i>
using ullong = integral_constant<unsigned long long, i>
related
template<typename T, T v>
template<std::size_t i>
using size_t = integral_constant<std::size_t, i>
related
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, "");
template<typename T, T v>
template<bool b>
constexpr bool_<b> bool_c {}
related
template<typename T, T v>
constexpr auto true_c = bool_c<true>
related
template<typename T, T v>
constexpr auto false_c = bool_c<false>
related
template<typename T, T v>
template<char c>
constexpr char_<c> char_c {}
related
template<typename T, T v>
template<short i>
constexpr short_<i> short_c {}
related
template<typename T, T v>
template<unsigned short i>
constexpr ushort_<i> ushort_c {}
related
template<typename T, T v>
template<int i>
constexpr int_<i> int_c {}
related
template<typename T, T v>
template<unsigned int i>
constexpr uint<i> uint_c {}
related
template<typename T, T v>
template<long i>
constexpr long_<i> long_c {}
related
template<typename T, T v>
template<unsigned long i>
constexpr ulong<i> ulong_c {}
related
template<typename T, T v>
template<long long i>
constexpr llong<i> llong_c {}
related
template<typename T, T v>
template<unsigned long long i>
constexpr ullong<i> ullong_c {}
related
template<typename T, T v>
template<std::size_t i>
constexpr size_t<i> size_c {}
related
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

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

Call a function n times.

times allows a nullary function to be invoked n times:

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");

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;
BOOST_HANA_CONSTEXPR_LAMBDA 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");

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.