This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.
3994.adaptor(args...)(r)
is not equivalent to std::bind_back(adaptor, args...)(r)
Section: 25.7.2 [range.adaptor.object] Status: New Submitter: Hewill Kang Opened: 2023-10-11 Last modified: 2023-11-03
Priority: 4
View other active issues in [range.adaptor.object].
View all other issues in [range.adaptor.object].
View all issues with New status.
Discussion:
25.7.2 [range.adaptor.object] p8 specifies that:
The expression
adaptor(args...)
produces a range adaptor closure objectf
that is a perfect forwarding call wrapper (22.10.4 [func.require]) with the following properties:
According to the subsequent description, it can be inferred that the behavior is similar to std::bind_back(adaptor, args...)
which also returns a perfect forwarding call wrapper.
Every call wrapper (22.10.3 [func.def]) meets the Cpp17MoveConstructible and Cpp17Destructible requirements.
In order to conform with the specification, standard functions that return perfect forwarding call wrappers such as std::bind_front/back
and std::not_fn
all Mandates that (is_constructible_v<BoundArgs, Args> && ...)
and (is_move_constructible_v<BoundArgs> && ...)
are each true
, the former condition corresponds to 25.7.2 [range.adaptor.object] p8:
The expression
adaptor(args...)
is well-formed if and only if the initialization of the bound argument entities of the result, as specified above, are all well-formed.
However, the latter does not have a corresponding description in <ranges>
. In other words, range adaptor objects do not explicitly indicate that the bound argument must be move-constructible. This results in implementation divergence for some uncommon types (demo):
#include <ranges> #include <string_view> constexpr struct WeirdFive { WeirdFive() = default; WeirdFive(const WeirdFive&) = default; constexpr operator int() const { return 5; } WeirdFive(WeirdFive&&) = delete; } five; constexpr std::string_view sv{"hello"}; static_assert(sv == std::views::take(five)(sv)); // libstdc++/libc++ reject, MSVC-STL accepts
Above, libstdc++ always moves arguments into internal members, which leads to hard errors in the member initializer list; libc++ uses std::bind_back
for argument binding, which also leads to hard errors in the function body as the former requires arguments to be move-constructible; MSVC-STL is the most compliant with current wording.
[2023-11-02; Reflector poll]
Set priority to 4 after reflector poll.
Proposed resolution:
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4