If I theoretically have a sequence of integers like
std::integer_sequence
How can I filter it with
Filtering a sequence is equivalent to transforming a sequence of values into a sequence of sequences of at most one value and then concatenating them. That is, filtering the even values from <0,1,2,3>
would be the same as transforming that into the sequence <<0>,<>,<2>,<>>
and concatenating to yield <0,2>
.
With C++17, this takes remarkably little code. We'll start with our own value and sequence type (you can easily convert a std::integer_sequence
to a value_sequence
):
template
struct value { };
template
struct value_sequence { };
The reason we use our own is so we can add operators to it. Like +
:
template
constexpr value_sequence operator+(value_sequence,
value_sequence )
{
return {};
}
We'll use that for concatenation. Next, we add a function to transform a single value into a sequence of zero or one element:
template
constexpr auto filter_single(value, F predicate) {
if constexpr (predicate(Val)) {
return value_sequence{};
}
else {
return value_sequence<>{};
}
}
And lastly, we just need our top-level filter
to put it all together:
template
constexpr auto filter(value_sequence, F predicate) {
return (filter_single(value{}, predicate) + ...);
}
Usage from the original example:
constexpr auto evens = filter(
value_sequence<0, 1, 2, 3, 4, 5, 6, 7, 8, 9>{},
[](int i) constexpr { return i%2 == 0; });
How cool is C++17!