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.

### 3680. Constructor of `move_only_function` with empty `ref`-qualifier is over-constrained

Section: 20.14.17.4.3 [func.wrap.move.ctor] Status: New Submitter: Zhihao Yuan Opened: 2022-02-27 Last modified: 2022-03-04

Priority: 2

View other active issues in [func.wrap.move.ctor].

View all other issues in [func.wrap.move.ctor].

View all issues with New status.

Discussion:

The following test compiles and holds:

>     struct X
>     {
>       int operator()() & { return 1; }  // #1
>       int operator()() && { return 2; } // #2
>     };

>     using T = move_only_function<int()>;
>     assert(T(X{})() == 1);

In other words, `#2` is never used. But if you really remove `#2`, the code doesn't compile.

The change was introduced between P0288R5 and P0288R6, with an intention (assumed) to require `move_only_function<R(Args...) cv>` erasing callable objects with `operator()` without `ref`-qualifiers. But the actual outcome outlawed programs that were valid when using `std::function`.

It also outlaws future programs such as

>     T x = [captures](this auto&) { return ...; }

where declaring `this auto&&` without forwarding only to satisfy `move_only_function`'s constraints would be strange.

[2022-03-04; Reflector poll]

Set priority to 2 after reflector poll. Probably needs a paper for LEWG.

Proposed resolution:

This wording is relative to N4901.

1. Modify 20.14.17.4.3 [func.wrap.move.ctor] as indicated:

   >     template<class VT>
   >       static constexpr bool is-callable-from = see below;

   > > -1- If `noex` is `true`, `is-callable-from<VT>` is equal to:

   > > >     is_nothrow_invocable_r_v<R, VT cv ref, ArgTypes...> &&
   > > >     is_nothrow_invocable_r_v<R, VT inv-quals, ArgTypes...>

   > > Otherwise, `is-callable-from<VT>` is equal to:

   > > >     is_invocable_r_v<R, VT cv ref, ArgTypes...> &&
   > > >     is_invocable_r_v<R, VT inv-quals, ArgTypes...>