3981. Range adaptor closure object is underspecified for its return type

Section: 25.7.2 [range.adaptor.object] Status: Tentatively NAD Submitter: Hewill Kang Opened: 2023-08-22 Last modified: 2024-06-24

Priority: Not Prioritized

View other active issues in [range.adaptor.object].

View all other issues in [range.adaptor.object].

View all issues with Tentatively NAD status.

Discussion:

In order to provide pipe support for user-defined range adaptors, P2387R3 removed the specification that the adaptor closure object returns a view, which conforms to the wording of ranges::to.

However, the current wording seems to be too low-spec so that the range adaptor closure object can return any type or even void. This makes it possible to break the previous specification when returning types that don't make sense, for example:

#include <ranges>

struct Closure : std::ranges::range_adaptor_closure<Closure> {
  struct NonCopyable {
    NonCopyable(const NonCopyable&) = delete;
  };

  const NonCopyable& operator()(std::ranges::range auto&&);
};

auto r = std::views::iota(0) | Closure{}; // hard error in libstdc++ and MSVC-STL

Above, since the return type of the pipeline operator is declared as auto, this causes the deleted copy constructor to be invoked in the function body and produces a hard error.

The proposed resolution adds a specification for the range adaptor closure object to return a cv-unqualified class type.

[2023-10-30; Reflector poll]

Set status to Tentatively NAD. "The wording says R | C is equivalent to C(R), not auto(C(R))."

Proposed resolution:

This wording is relative to N4958.

  1. Modify 25.7.2 [range.adaptor.object] as indicated:

    -1- A range adaptor closure object is a unary function object that accepts a range argument. For a range adaptor closure object C and an expression R such that decltype((R)) models range, the following expressions are equivalent:

    […]

    -2- Given an object t of type T, where

    1. (2.1) — t is a unary function object that accepts a range argument and returns a cv-unqualified class object,

    2. […]

    then the implementation ensures that t is a range adaptor closure object.