tuple_map(3) | tuple_map(3) |
tuple_map - apply function to elements in tuple
#include <cfl/tuple/tuple_map.hpp>
template <typename F, typename... ARGS>
auto tuple_map (F && f, ARGS &&... args);
auto f = [] (int arg) { return arg + 1; };
tuple_map (f, tuple (0, 1)) == tuple (1, 2);
auto g = [] (auto && arg) { return sizeof (arg); }
tuple_c <tuple_c <char [1], char [2]>, char [4]> u;
tuple_map (g, u) == tuple (tuple (1,2), 4);
tuple_Map (g, u) == 7;
tuple_map1 (g, u) == tuple (3,4);
tuple_Map1 (g, u) == tuple (3,4);
Roughly, tuple_map
applies a function to all elements in a tuple, and returns
the results in a new tuple. As the function may be shape-polymorphic and the
tuple multi-dimensional, a more precise description follows below.
In general, a map is an higher-order function of arrays. For a unary function
f
and an array A
, map is defined as:
A = {a(1)...a(n)}
map (f, A) = {f(a(1))...f(a(n))} (1)
The function f
may be shape-polymorphic, i.e. accept arrays of arbitrary
shape, not only dimensionless elements. {a(i)}
represents the collection of
subarrays of A
for which f(a(i))
is applicable. The collection is formed by
each of the tuple elements of A
, possibly recursively or not at all (see
below). It should not be confused with the mathematical concept of a subset,
which can be formed by arbitrary combinations of elements of the set.
If the collection of subarrays is not unqiue, i.e. f
accepts arguments of more
than one dimension, there are two variants of map using either the smallest or
the largest collection of subarrays. In other words, either map A
in as
small or as large chunks as possible. The two variants are named tuple_map
and
tuple_Map
respectively, where the lower-case m denotes small chunks, and the
capital M large chunks.
The collection of subarrays may consist of A
itself, meaning a map may be
equivalent to a plain f (A)
. There are variants of map requiring the subsets
to be strictly smaller than A
, named tuple_map1
and tuple_Map1
.
Full control over when f
should be applied or not, is achieved by augumenting
f
with a predicate, see enable_if(3) for details.
Map accepts functions with higher arity. For a binary function g
and two
arrays A
and B
, map is defined as:
map (g, A, B) = {f(a(1), b(1))...f(a(n), b(n))}
Also here {a(i), b(i)}
represents the collection of subarrays of A
and B
for which {f(a(i), b(i))}
is applicable. This implies the collections
{a(i)}
and {b(i)}
must have the same number of elements, which places some
restrictions on argument shapes.
Finally, f
may have void
return type, if it does so for all subarrays in
the map. Then map also has void
return type.
As in the definition of map (1) above.
tuple_map
is a container function.
cfl::tuple_map
should not to be confused with std::map
, which is an
associative container operating on iterators.
The mix of underscore and camelCase in tuple_Map
is maybe not very pleasing to
the eye. Also, the names of two functions tuple_map
and tuple_Map
differing
only in a single case may not be entirely safe. But for brevity, these are the
chosen names in CFL.
tuple(3), enable_if(3)