This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of Resolved status.

### 3509. Range adaptor objects are underspecified

Section: 26.7.2 [range.adaptor.object] Status: Resolved Submitter: Tim Song Opened: 2020-12-15 Last modified: 2021-06-14

Priority: 2

View all issues with Resolved status.

Discussion:

There is implementation divergence in the handling of this example:

>     template<class F>
>     auto filter(F f) {
>       return std::views::filter(f);
>     }
>     std::vector<int> v = {1, 2, 3, 4};
>     auto f = filter([i = std::vector{4}] (auto x) { return x == i[0]; });
>     auto x = v | f;

libstdc++'s `views::filter` stores a reference to the argument if it is passed as an lvalue, so `f` contains a dangling reference in the above example. MSVC's `views::filter` always stores a copy, and forwards that as either an lvalue or an rvalue depending on the range adaptor closure object's value category.

MSVC's behavior here seems desirable and is consistent with range-v3's behavior as well: the ability to form range adapter pipelines like this is an important feature, and there's nothing in the above example that even hints at a dangling reference problem.

However, the wording in 26.7.2 [range.adaptor.object] is unclear at best about exactly how the arguments are stored in the `adaptor(args...)` case; arguably, the requirement that `adaptor(range, args...)` be equivalent to `adaptor(args...)(range)` may even rule out the ability to make an extra copy. Certainly nothing in the wording guarantees that it is safe to reuse lvalue range pipelines (that is, `v | f` doesn't move from `f`).

[2021-01-15; Telecon prioritization]

Set priority to 2 following reflector and telecon discussions.

[2021-06-13 Resolved by the adoption of P2281R1 at the June 2021 plenary. Status changed: New → Resolved.]

Proposed resolution: