This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++20 status.

### 3238. Insufficiently-defined behavior of `std::function` deduction guides

Section: 20.14.17.3.2 [func.wrap.func.con] Status: C++20 Submitter: Louis Dionne Opened: 2019-07-17 Last modified: 2021-02-25

Priority: Not Prioritized

View other active issues in [func.wrap.func.con].

View all other issues in [func.wrap.func.con].

View all issues with C++20 status.

Discussion:

The following code is currently undefined behavior:

>     #include <functional>

>     struct R { };
>     struct f0 { R operator()() && { return {}; } };

>     int main() { std::function f = f0{}; }

The reason is that 20.14.17.3.2 [func.wrap.func.con]/12 says:

> This deduction guide participates in overload resolution only if `&F::operator()` is well-formed when treated as an unevaluated operand. In that case, if `decltype(&F::operator())` is of the form `R(G::*)(A...) cv &opt noexceptopt` for a class type `G`, then the deduced type is `function<R(A...)>`.

However, it does not define the behavior when `&F::operator()` is well-formed but not of the required form (in the above example it's of the form `R(G::*)(A...) &&`, which is rvalue-reference qualified instead of optionally-lvalue-reference qualified). libc++'s implementation of the deduction guide SFINAE's out when either `&F::operator()` is not well-formed, or it is not of the required form. It seems like mandating that behavior in the Standard is the way to go.

Previous resolution [SUPERSEDED]:

> This wording is relative to N4820.

> 1. Modify 20.14.17.3.2 [func.wrap.func.con] as indicated:

>    >     template<class F> function(F) -> function<see below>;

>    > > -12- Remarks: This deduction guide participates in overload resolution only if `&F::operator()` is well-formed when treated as an unevaluated operand, and its type is of the form `R(G::*)(A...) cv &opt noexceptopt` for a class type `G` and a sequence of types `A...`. In that case, if `decltype(&F::operator())` is of the form `R(G::*)(A...) cv &opt noexceptopt` for a class type `G`, then the deduced type is `function<R(A...)>`.

[2020-02-13; Prague]

LWG improves wording matching Marshall's Mandating paper.

[Status to Immediate on Friday in Prague.]

Proposed resolution:

This wording is relative to N4849.

1. Modify 20.14.17.3.2 [func.wrap.func.con] as indicated:

   > [Drafting note: This edit should be used instead of the corresponding edit in P1460]

   >     template<class F> function(F) -> function<see below>;

   > > -?- Constraints: `&F::operator()` is well-formed when treated as an unevaluated operand and `decltype(&F::operator())` is of the form `R(G::*)(A...) cv &opt noexceptopt` for a class type `G`.

   > > -12- Remarks: This deduction guide participates in overload resolution only if `&F::operator()` is well-formed when treated as an unevaluated operand. In that case, if `decltype(&F::operator())` is of the form `R(G::*)(A...) cv &opt noexceptopt` for a class type `G`, then t The deduced type is `function<R(A...)>`.