Skip to content

<functional>: Avoid pessimization in std::move_only_function assignment operators #2278

Description

Does the below look like a valid LWG issue?


In std::move_only_function wg21-p0288, some assignments are defined in terms of swap (in [func.wrap.mov.con])

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 implementation of assignment via swap is normally useful for exception safety.

However, this is superfluous here, as move_only_function is moved with noexcept.

At the same time, this approach causes extra moving of function. This may be expensive due to large small-functor-optimization buffer, and due to calling user-provided move constructor for small factor.

Looks like the optimizations made by implementation to avoid extra moving cannot always be made, as calling user-provided move constructor is observable.

I propose:
add nocexcept to move assingment move_only_function& operator=(move_only_function&& f) noexcept;
change the mentioned methods to say:

move_only_function& operator=(move_only_function&& f);
Effects: the target object of this is set to the target object of f before the assignment and leaves f in a valid state with an unspecified value.

template<class F> move_only_function& operator=(F&& f);
Effects: Equivalent to: *this = move_only_function(std::forward<F>(f));

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionFurther information is requested

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions