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.

3642. move_only_function assignment operators seem to be defined suboptimal

Section: 22.10.17.4.3 [func.wrap.move.ctor] Status: New Submitter: Alexander Guteniev Opened: 2021-11-20 Last modified: 2022-01-30

Priority: 3

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:

22.10.17.4.3 [func.wrap.move.ctor]/22 and 22.10.17.4.3 [func.wrap.move.ctor]/25 define the effects of assignment as following:

move_only_function& operator=(move_only_function&& f);

Effects: Equivalent to: move_only_function(std::move(f)).swap(*this);

[…]
template<class F> move_only_function& operator=(F&& f);

Effects: Equivalent to: move_only_function(std::forward<F>(f)).swap(*this);

The assignment via swap with temporary makes the implementation to do the following:

As everything is noexcept here, I think it can be short cut to just:

Looks like the implementation cannot do such optimization in a generic case with small functor optimization enabled and non-trivial move constructor for the new target and with non-trivial destruction of the previous target, since the difference is observable.

Apparently the optimization is precluded for no reason.

[2022-01-30; Reflector poll]

Set priority to 3 after reflector poll. Some suggestions for NAD, but others disagreed.

Proposed resolution:

This wording is relative to N4901.

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

    move_only_function& operator=(move_only_function&& f);
    

    -22- Effects: Sets the target object of this to the target object of f before the assignment and leaves f in a valid state with an unspecified value.Equivalent to: move_only_function(std::move(f)).swap(*this);

    […]
    template<class F> move_only_function& operator=(F&& f);
    

    -25- Effects: Equivalent to: *this = move_only_function(std::forward<F>(f)).swap(*this);