Last time, we wrote offset_sequence_t
, which takes an existing sequence and adds a fixed value to each element. This is the sort of index manipulation you may want to generalize. So let’s generalize it.
template<std::size_t F(std::size_t), typename Seq> struct modify_sequence; template<std::size_t F(std::size_t), std::size_t... Ints> struct modify_sequence<F, std::index_sequence<Ints...>> { using type = std::index_sequence<F(Ints)...>; }; template<std::size_t F(std::size_t), typename Seq> using modify_sequence_t = typename modify_sequence<F, Seq>::type;
Instead of hard-coding the + 1
operation, we let you specify the modification operation F
. Since this is template metaprogramming, the modification operation must be something that can be done at compile time. This means that it needs to be a constexpr
function.
constexpr std::size_t add_one(std::size_t v) { return v + 1; } // example = std::index_sequence<4, 2, 5> using example = modify_sequence_t< add_one, std::index_sequence<3, 1, 4>>;
Of course, this gets annoying having to write add_whatever
each time you want to add something, so we can generalize the add_one
function.
template<int N> constexpr std::size_t add_N(std::size_t v) { return v + N; } // example = std::index_sequence<4, 2, 5> using example = modify_sequence_t< add_N<1>, std::index_sequence<3, 1, 4>>; // example2 = std::index_sequence<2, 0, 3> using example2 = modify_sequence_t< add_N<-1>, std::index_sequence<3, 1, 4>>;
It’s possible to write other helpers like, say, parallel_add_t
which adds two sequences elementwise, but that sort of thing isn’t needed in practice much.
Next time, we’ll try to invert tuple_element_t
.
0 comments