c++range-v3

range-v3: Joining piped ranges with a delimeter


I'm trying to build a basic demo of the range-v3 library: take some integers, filter out odd values, stringify them, then join those into a comma-separated list. For example, { 8, 6, 7, 5, 3, 0, 9 } becomes "8, 6, 0". From reading the docs and going through examples, it seems like the naïve solution would resemble:

string demo(const vector<int>& v)
{
    return v |
        ranges::view::filter([](int i) { return i % 2 == 0; }) |
        ranges::view::transform([](int i) { return to_string(i); }) |
        ranges::view::join(", ");
}

but building on Clang 7 fails with a static assertion that one, "Cannot get a view of a temporary container". Since I'm collecting the result into a string, I can use the eager version - action::join - instead:

string demo(const vector<int>& v)
{
    return v |
        ranges::view::filter([](int i) { return i % 2 == 0; }) |
        ranges::view::transform([](int i) { return to_string(i); }) |
        ranges::action::join;
}

but the eager version doesn't seem to have an overload that takes a delimiter.

Interestingly, the original assertion goes away if you collect join's inputs into a container first. The following compiles and runs fine:

string demo(const vector<int>& v)
{
    vector<string> strings = v |
        ranges::view::filter([](int i) { return i % 2 == 0; }) |
        ranges::view::transform([](int i) { return to_string(i); });
    return strings | ranges::view::join(", ");
}

but this totally defeats the principle of lazy evaluation that drives so much of the library.

Why is the first example failing? If it's not feasible, can action::join be given a delimiter?


Solution

  • action::join should accept a delimiter. Feel free to file a feature request. The actions need a lot of love.