C++23 adds std::views::join_with, which takes a range-of-ranges and a pattern and produces the elements of the inner ranges with the pattern interspersed.
We should have it too.
As always though, naming is hard. Our version of views::join is called flatten, to avoid the confusion that occurs in the ranges world between views::join (which takes a range-of-ranges) and views::concat (which takes a variadic pack of ranges and glues them together). So we could call our version flatten_with, following the same pattern. On the other hand, Range-V3 (unlike C++23) instead provides a second overload of views::join which takes an extra parameter. We could do the same and provide another overload of flatten, although I'm not particularly keen on that.
Another option could be to name our version of the adaptor just join, as it performs the opposite action to split: that is, seq.split(pattern).join(pattern) and seq_of_seqs.join(pattern).split(pattern) should each end up as a long-winded round-trip. Split and join as the complement of each other seems pretty nice, but it does again raise the possibility of join being mixed up with chain (our version of views::concat).
Yet another option could be intersperse or interleave, although either name seems more like it should take a pair (or pack?) of sequences and alternate between an element of the first sequence and an element of the second sequence until one is exhausted.
(D provides roundRobin(), which takes a variadic number of ranges and produces elements of each in turn until all are exhausted, which is a slightly different algorithm -- though I like that one too.)
C++23 adds
std::views::join_with
, which takes a range-of-ranges and a pattern and produces the elements of the inner ranges with the pattern interspersed.We should have it too.
As always though, naming is hard. Our version of
views::join
is calledflatten
, to avoid the confusion that occurs in the ranges world betweenviews::join
(which takes a range-of-ranges) andviews::concat
(which takes a variadic pack of ranges and glues them together). So we could call our versionflatten_with
, following the same pattern. On the other hand, Range-V3 (unlike C++23) instead provides a second overload ofviews::join
which takes an extra parameter. We could do the same and provide another overload offlatten
, although I'm not particularly keen on that.Another option could be to name our version of the adaptor just
join
, as it performs the opposite action tosplit
: that is,seq.split(pattern).join(pattern)
andseq_of_seqs.join(pattern).split(pattern)
should each end up as a long-winded round-trip. Split and join as the complement of each other seems pretty nice, but it does again raise the possibility ofjoin
being mixed up withchain
(our version ofviews::concat
).Yet another option could be
intersperse
orinterleave
, although either name seems more like it should take a pair (or pack?) of sequences and alternate between an element of the first sequence and an element of the second sequence until one is exhausted.(D provides
roundRobin()
, which takes a variadic number of ranges and produces elements of each in turn until all are exhausted, which is a slightly different algorithm -- though I like that one too.)