forked from lwg/issues
-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
New issue from Hewill Kang: " adaptor(args...)(r) is not equivalent t…
…o std::bind_back(adaptor, args...)(r)"
- Loading branch information
Showing
1 changed file
with
70 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
<?xml version='1.0' encoding='utf-8' standalone='no'?> | ||
<!DOCTYPE issue SYSTEM "lwg-issue.dtd"> | ||
|
||
<issue num="3994" status="New"> | ||
<title><tt>adaptor(args...)(r)</tt> is not equivalent to <tt>std::bind_back(adaptor, args...)(r)</tt></title> | ||
<section><sref ref="[range.adaptor.object]"/></section> | ||
<submitter>Hewill Kang</submitter> | ||
<date>11 Oct 2023</date> | ||
<priority>99</priority> | ||
|
||
<discussion> | ||
<p> | ||
<sref ref="[range.adaptor.object]"/> p8 specifies that: | ||
</p> | ||
<blockquote><p> | ||
The expression <tt>adaptor(args...)</tt> produces a range adaptor closure object <tt>f</tt> that is a perfect forwarding | ||
call wrapper (<sref ref="[func.require]"/>) with the following properties: | ||
</p></blockquote> | ||
<p> | ||
According to the subsequent description, it can be inferred that the behavior is similar to | ||
<tt>std::bind_back(adaptor, args...)</tt> which also returns a perfect forwarding call wrapper. | ||
<p/> | ||
Among them, "A <i>perfect forwarding call wrapper</i> is an argument forwarding call wrapper | ||
that forwards its state entities to the underlying call expression" according to <a href="https://wg21.link/func.require">[func.require]</a>/4, and call wrapper in <a href="https://wg21.link/func.require">[func.require]</a>/3 is described as: | ||
</p> | ||
<blockquote><p> | ||
Every call wrapper (<sref ref="[func.def]"/>) meets the <i>Cpp17MoveConstructible</i> and <i>Cpp17Destructible</i> requirements. | ||
</p></blockquote> | ||
<p> | ||
In order to conform with the specification, standard functions that return perfect forwarding call wrappers such as | ||
<tt>std::bind_front/back</tt> and <tt>std::not_fn</tt> all <i>Mandates</i> that | ||
<tt>(is_constructible_v<BoundArgs, Args> && ...)</tt> and | ||
<tt>(is_move_constructible_v<BoundArgs> && ...)</tt> are each <tt>true</tt>, | ||
the former condition corresponds to <sref ref="[range.adaptor.object]"/> p8: | ||
</p> | ||
<blockquote><p> | ||
The expression <tt>adaptor(args...)</tt> is well-formed if and only if the initialization of the bound argument | ||
entities of the result, as specified above, are all well-formed. | ||
</p></blockquote> | ||
<p> | ||
However, the latter does not have a corresponding description in <tt><ranges></tt>. 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 (<a href="https://godbolt.org/z/r6Gq8W6qe">demo</a>): | ||
</p> | ||
<blockquote><pre> | ||
#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)); // <span style="color:red;font-weight:bolder">libstdc++/libc++ reject, MSVC-STL accepts</span> | ||
</pre></blockquote> | ||
<p> | ||
Above, libstdc++ always moves arguments into internal members, which leads to hard errors in the member initializer list; | ||
libc++ uses <tt>std::bind_back</tt> 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. | ||
</p> | ||
</discussion> | ||
|
||
<resolution> | ||
</resolution> | ||
|
||
</issue> |