Title
std::function should not return dangling references
Status
resolved
Section
[func.wrap.func.con]
Submitter
Brian Bi

Created on 2016-11-03.00:00:00 last changed 24 months ago

Messages

Date: 2022-11-25.09:41:00

Proposed resolution:

This wording is relative to N4618.

  1. Add a second paragraph to the remarks section of [func.wrap.func.con]:

    template<class F> function(F f);
    

    -7- Requires: F shall be CopyConstructible.

    -8- Remarks: This constructor template shall not participate in overload resolution unless

    • F is Lvalue-Callable ([func.wrap.func]) for argument types ArgTypes... and return type R, and

    • If R is type "reference to T" and INVOKE(ArgTypes...) has value category V and type U:

      • V is a prvalue, U is a class type, and T is not reference-related ([dcl.init.ref]) to U, and

      • V is an lvalue or xvalue, and either U is a class type or T is reference-related to U.

    […]

Date: 2022-11-15.00:00:00

[ 2022-11-25; see EWG 1370 ]

Date: 2022-08-24.00:00:00

[ 2022-08-24 Resolved by P2255R2. Status changed: EWG → Resolved. ]

Date: 2018-08-23.00:00:00

[ 2018-08-23 Batavia Issues processing ]

Really needs a language change to fix this. Status to EWG.

Date: 2017-07-16.20:43:29

[ 2016-07, Toronto Saturday afternoon issues processing ]

Billy to work with Brian to rework PR. Status to Open

Date: 2017-02-02.00:41:18

[ Issues Telecon 16-Dec-2016 ]

Priority 2

Date: 2016-11-15.00:00:00

[ 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.

Date: 2016-11-03.00:00:00

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.

A minimal example of well-formed code under the current standard that exhibits this issue:

#include <functional>

int main() 
{
  std::function<const int&()> F([]{ return 42; });
  int x = F(); // oops!
}
History
Date User Action Args
2022-11-25 09:41:00adminsetmessages: + msg13112
2022-08-24 18:47:42adminsetmessages: + msg12706
2022-08-24 18:47:42adminsetstatus: ewg -> resolved
2018-08-24 13:31:33adminsetmessages: + msg10116
2018-08-24 13:31:33adminsetstatus: open -> ewg
2017-07-16 20:43:29adminsetmessages: + msg9421
2017-07-16 20:43:29adminsetstatus: new -> open
2016-12-16 20:56:38adminsetmessages: + msg8744
2016-12-10 12:34:17adminsetmessages: + msg8706
2016-12-10 12:34:17adminsetmessages: + msg8705
2016-11-03 00:00:00admincreate