c++algorithmstlstl-algorithm

Algorithm name?: Concatenate the ranges returned by a function applied to each element of a range


Maybe I'm missing something. Is there a function in <algorithm> that does this? If not, what would you call it? It seems like a particular flavor of transform-reduce that is so specific it needs a name:

template <typename Iter, typename OutIter, typename Fn>
void transformed_concatenated(Iter beg, Iter end, OutIter out, Fn f) {
    for (; beg != end; ++beg) {
        for (auto& x : f(*beg)) {
            *out++ = std::move(x);
        }
    }
    return out;
}

That is, if I do

const std::vector<int> input { 0, 1, 2, 3 };
const auto f = [](int n) { return std::vector<int>(n, n * 2 + 1); };
std::vector<int> result;
transformed_concatenated(input.begin(), input.end(), std::back_inserter(result), f);

I would get 3, 5, 5, 7, 7, 7.

Something like it could be done with std::transform_reduce, but I feel like it loses something.


Solution

  • With the ranges and views introduced in C++20, you could write:

    std::ranges::copy(input 
                      | std::views::transform(f) 
                      | std::views::join, 
                      std::back_inserter(result));
    

    Here's a demo.


    Note that your function f is incorrect. It needs to be

    const auto f = [](int n) { return std::vector<int>(n, n); };
                                                   // ^____^
    

    to get the desired output 1 2 2 3 3 3. If you use braces to construct the vector, you'll get a vector of 2 elements, both with the value n, and the output will be 1 1 2 2 3 3.