Boost.Hana: boost::hana::integral_constant< T, v > Struct Template Reference

| Boost.Hana 1.0.0 Your standard library for metaprogramming |

Synopsis of associated functions | Friends | Static Public Member Functions | List of all members
boost::hana::integral_constant< T, v > Struct Template Reference
Data types

## 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_constant`s 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_constant`s, 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 `Constant`s 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_constant`s 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,
   integral_constant<T, v>::value == v // of type T
   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 `Constant`s, 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

  T | The type of the value to hold in the `integral_constant`. It must be an integral type.
  v | The 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:

int_<3>::times(f)

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_constant`s; 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_constant`s instead of normal integers. Side effects can also be done in the function passed to `times` and `times.with_index`.