integer_sequence Class
Represents an integer sequence. Can be used to deduce and expand parameter packs in variadic types such as std::tuple<T...> that are passed as arguments to a function.
Syntax
template <class T, T... Vals>
struct integer_sequence
Parameters
T
The type of the values; must be an integral type: bool, char, char16_t, char32_t, wchar_t, or signed or unsigned integer types.
Vals
A non-type parameter pack that represents a sequence of values of integral type T.
Members
Name | Description |
---|---|
static size_t size() noexcept |
The number of elements in the sequence. |
typedef T value_type |
The type of each element in the sequence. Must be an integral type. |
Remarks
A parameter pack that is passed directly to a function can be unpacked without any special library helpers. When a parameter pack is part of a type that is passed to a function, and you need indices to access the elements, then the easiest way to unpack it is to use integer_sequence
and its related type aliases make_integer_sequence
, index_sequence
, make_index_sequence
, and index_sequence_for
.
Example
The following example is based on the original proposal N3658. It shows how to use an integer_sequence
to create a std::tuple
from a std::array<T,N>
, and how to use an integer_sequence
to get at the tuple members.
In the a2t
function, an index_sequence
is an alias of integer_sequence
based on the size_t
integral type. make_index_sequence
is an alias that at compile time creates a zero-based index_sequence
with the same number of elements as the array that is passed in by the caller. a2t
passes the index_sequence
by value to a2t_
, where the expression a[I]...
unpacks I
, and then the elements are being fed to make_tuple
which consumes them as individual arguments. For example, if the sequence contains three elements, then make_tuple
is called as make_tuple(a[0], a[1], a[2]). The array elements themselves can of course be any type.
The apply function accepts a std::tuple, and produces an integer_sequence
by using the tuple_size
helper class. Note that std::decay_t is necessary because tuple_size does not work with reference types. The apply_
function unpacks the tuple members and forwards them as separate arguments to a function call. In this example the function is a simple lambda expression that prints out the values.
#include <stddef.h>
#include <iostream>
#include <tuple>
#include <utility>
#include <array>
#include <string>
using namespace std;
// Create a tuple from the array and the index_sequence
template<typename Array, size_t... I>
auto a2t_(const Array& a, index_sequence<I...>)
{
return make_tuple(a[I]...);
}
// Create an index sequence for the array, and pass it to the
// implementation function a2t_
template<typename T, size_t N>
auto a2t(const array<T, N>& a)
{
return a2t_(a, make_index_sequence<N>());
}
// Call function F with the tuple members as separate arguments.
template<typename F, typename Tuple = tuple<T...>, size_t... I>
decltype(auto) apply_(F&& f, Tuple&& args, index_sequence<I...>)
{
return forward<F>(f)(get<I>(forward<Tuple>(args))...);
}
// Create an index_sequence for the tuple, and pass it with the
// function object and the tuple to the implementation function apply_
template<typename F, typename Tuple = tuple<T...>>
decltype(auto) apply(F&& f, Tuple&& args)
{
using Indices = make_index_sequence<tuple_size<decay_t<Tuple>>::value >;
return apply_(forward<F>(f), forward<Tuple>(args), Indices());
}
int main()
{
const array<string, 3> arr { "Hello", "from", "C++14" };
//Create a tuple given a array
auto tup = a2t(arr);
// Extract the tuple elements
apply([](const string& a, const string& b, const string& c) {cout << a << " " << b << " " << c << endl; }, tup);
char c;
cin >> c;
}
To make an index_sequence
for a parameter pack, use index_sequence_for
<T...> which is an alias for make_index_sequence
<sizeof...(T)>
Requirements
Header: <type_traits>
Namespace: std