std::function
should not return dangling referencesSection: 22.10.17.3.2 [func.wrap.func.con] Status: Resolved Submitter: Brian Bi Opened: 2016-11-03 Last modified: 2022-11-25
Priority: 2
View all other issues in [func.wrap.func.con].
View all issues with Resolved status.
Discussion:
If a std::function
has a reference as a return type, and that reference binds to a prvalue
returned by the callable that it wraps, then the reference is always dangling. Because any use of such
a reference results in undefined behaviour, the std::function
should not be allowed to be
initialized with such a callable. Instead, the program should be ill-formed.
#include <functional> int main() { std::function<const int&()> F([]{ return 42; }); int x = F(); // oops! }
[2016-11-22, David Krauss comments and suggests wording]
Indirect bindings may also introduce temporaries inside std::function
, e.g.:
void f(std::function<long const&()>); // Retains an observer to a long. void g() { int v; f([&]()->int& { return v; } ); // int lvalue binds to long const& through a temporary. }
A fix has been implemented. Conversions that may be conversion operators are allowed, though, because those can produce legitimate glvalues. Before adopting this, it need to be considered considered whether there should be SFINAE or a hard error.
[Issues Telecon 16-Dec-2016]
Priority 2
[2016-07, Toronto Saturday afternoon issues processing]
Billy to work with Brian to rework PR. Status to Open
[2018-08-23 Batavia Issues processing]
Really needs a language change to fix this. Status to EWG.
[2022-08-24 Resolved by P2255R2. Status changed: EWG → Resolved.]
[2022-11-25; see EWG 1370]
Proposed resolution:
This wording is relative to N4618.
Add a second paragraph to the remarks section of 22.10.17.3.2 [func.wrap.func.con]:
template<class F> function(F f);-7- Requires:
-8- Remarks: This constructor template shall not participate in overload resolution unlessF
shall beCopyConstructible
.
F
is Lvalue-Callable (22.10.17.3 [func.wrap.func]) for argument typesArgTypes...
and return typeR
, andIf
R
is type "reference toT
" andINVOKE(ArgTypes...)
has value categoryV
and typeU
:
V
is a prvalue,U
is a class type, andT
is not reference-related (9.4.4 [dcl.init.ref]) toU
, and
V
is an lvalue or xvalue, and eitherU
is a class type orT
is reference-related toU
.[…]