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.
Section: 22.10.4 [func.require] Status: New Submitter: Tomasz KamiĆski Opened: 2025-08-19 Last modified: 2025-08-23
Priority: Not Prioritized
View other active issues in [func.require].
View all other issues in [func.require].
View all issues with New status.
Discussion:
The wording for argument forwarding call wrappers in 22.10.4 [func.require] p3,
This forwarding step delivers rvalue arguments as rvalue references and lvalue arguments as lvalue references.
requires that each wrapper binds a temporary to rvalue reference
(materializing it), and then pass that xvalue. This essentially
codifies an implementation where wrappers provide an operator()
that
accepts Args&&...
. This is fine for most of the wrappers.
bind_front(f)/bind_back(f)
without bound args could return a copy of f
bind_front<f>()/bind_back<f>()
could produce a
__function_wrapper<f>
, that for function pointers can be invoked using
a surrogate function call.
However, such implementation strategies are currently disallowed per
22.10.4 [func.require] p3, as invoking the function wrapper with
a prvalue bind_front(f)(T())
requires a temporary to be materialized,
and then moved into the parameter of f
. For example:
struct M { M() { std::cout << "Default" < std::endl; } M(M&& m) { std::cout << "Move" < std::endl; } }; struct F { void operator()(M m) {} } f;
The call f(M{})
will print only "Default
" but bind_front(f)(M{})
is
required to produce "Default
" and "Move
". We should allow
implementations to elide the move operations, but not require it.
The suggested changes by this issue have been
implemented in libstdc++
for bind_front/bind_back
.
Proposed resolution:
This wording is relative to N5014.
Modify 22.10.4 [func.require] as indicated:
-3- Every call wrapper (22.10.3 [func.def]) meets the Cpp17MoveConstructible and Cpp17Destructible requirements. An argument forwarding call wrapper is a call wrapper that can be called with an arbitrary argument list and delivers the arguments to the target object
as references. This forwarding step deliversrvalue arguments as rvalue references and lvalue arguments as lvalue references.:
(3.?) — lvalue arguments as lvalues,
(3.?) — xvalue arguments as xvalues,
(3.?) — prvalue arguments as either prvalues or xvalues.