3617. function/packaged_task deduction guides and deducing this

Section: 22.10.17.3.2 [func.wrap.func.con], 32.10.10.2 [futures.task.members] Status: C++23 Submitter: Barry Revzin Opened: 2021-10-09 Last modified: 2023-11-22

Priority: 2

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

View all issues with C++23 status.

Discussion:

With the adoption of deducing this (P0847), we can now create types whose call operator is an explicit object member function, which means that decltype(&F::operator()) could have pointer-to-function type rather than pointer-to-member-function type. This means that the deduction guides for std::function (22.10.17.3.2 [func.wrap.func.con]) and std::packaged_task (32.10.10.2 [futures.task.members]) will simply fail:

struct F {
  int operator()(this const F&) { return 42; }
};

std::function g = F{}; // error: decltype(&F::operator()) is not of the form R(G::*)(A...) cv &opt noexceptopt

We should update the deduction guides to keep them in line with the core language.

[2021-10-14; Reflector poll]

Set priority to 2 after reflector poll.

Previous resolution [SUPERSEDED]:

This wording is relative to N4892.

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

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

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

    -17- Remarks: The deduced type is function<R(A...)>.

  2. Modify 32.10.10.2 [futures.task.members] as indicated:

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

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

    -8- Remarks: The deduced type is packaged_task<R(A...)>.

[2021-10-17; Improved wording based on Tim Song's suggestion]

[2022-07-01; Reflector poll]

Set status to Tentatively Ready after nine votes in favour during reflector poll.

[2022-07-15; LWG telecon: move to Ready]

[2022-07-25 Approved at July 2022 virtual plenary. Status changed: Ready → WP.]

Proposed resolution:

This wording is relative to N4892.

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

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

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

    -17- Remarks: The deduced type is function<R(A...)>.

  2. Modify 32.10.10.2 [futures.task.members] as indicated:

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

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

    -8- Remarks: The deduced type is packaged_task<R(A...)>.