tuple_unfold(3) tuple_unfold(3)

NAME

tuple_unfold - generate tuple from seed

SYNOPSIS

#include <cfl/tuple/functions/tuple_unfold.hpp>

// generic form

tuple_unfold <PY, FY, SY> (init, u...);

// convenience overloads

tuple_unfold <N> ();
tuple_unfold <N> (f);
tuple_unfold <N> (g);

tuple_unfold <3> () == tuple (0,1,2);
tuple_unfold <3> ([] () { return 0; }) == tuple (0,0,0);
tuple_unfold <3> ([] (int u) { return u*2; }) == tuple (0,2,4);

DESCRIPTION

An unfold can be thought of as the opposite of a fold. Where a fold reduces many values to a singular value, an unfold generates many values from a singular value. Its general form may be a bit awkward for the most common user cases, so some convenience overloads are provided.

The convenience forms generate a tuple with N elements. The first form creates consecutive size_t elements starting at zero. The second form creates elements from invocations of the nullary function f. The third form creates elements by invoking the unary function g using the tuple index as argument.

The convenience forms all use a state of type std::integral_constant <size_t, N> (for which CFL has a shorthand natural_t <N>), with an initial N = 0.
The third conventience form converts the natural_t <N> state to a size_t run-time value before applying it to g.

The generic form assumes three factory arguments, PY, FY and SY, an initial state init, and an optional list U of convenience values.

PY <STATE, U...>    // predicate
FY <STATE, U...>    // new value
SY <STATE, U...>    // new state

The unfold proceeds stepwise by first asserting the predicate is true, then generating a new value, and finally retreiving the next state. All necessary arguments can be included in the state, but for convenience the optional list U will be passed to factories as well. This is to releive the burden of bundling arguments.

As the element types of the resulting tuple is determined at compile-time, the value of the predicate PY and the next state SY must be available at compile-time. There is no restriction on the types of the generated elements - the general case allows for arbitrary types to be returned from FY <STATE, U...>.

RETURN VALUES

A tuple with values.

NOTES

Due to the convenience overloads, tuple_unfold is a function template, not a function object as customary. As a consequence, it can not be used as argument to a function as easily.

Adhering to the general form, the result is not a constexpr. (A restriction on the state to be a type only and not hold run-time values would be enough to lift this limitation.)

As the state may have a run-time value, this implies a run-rime union storage for temporary states during the unfold. Although literal types stored in core unions are constant expressions, the implemenation of a variadic union is not a constant expression - at least not in void expressions. Whether this is a limitation of the language or the compiler remains to be seen. Anyway, constexpr under these conditions is a C++14 feature - which is not yet supported by the nvcc compiler (as of version 8.0).

SEE ALSO

tuple_fold(3), conventions(5), union(3), variant(3)