4255. move_only_function constructor should recognize empty copyable_functions

Section: 22.10.17.4.3 [func.wrap.move.ctor] Status: New Submitter: Tomasz Kamiński Opened: 2025-05-12 Last modified: 2025-05-12

Priority: Not Prioritized

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 standard currently requires that constructing move_only_function from empty copyable_function, creates an non-empty move_only_function, that contains an empty copyable_function as the target. For exampe: std::copyable_function<int(int)> ce; std::move_only_function<int(int)> me(ce); We require that invoking me(1) is undefined behavior (as it leads to call to the ce(1)), however it cannot be detected in the user code, as me != nullptr is true.

We should require that the move_only_function(F&& f) constructor to create an empty object, if f is instantiation of of copyable_function and f == nullptr is true, i.e. f does not contain target object.

This simplifies implementing avoidance of double wrapping per 22.10.17.1 [func.wrap.general] p2, as transfering the target produces empty functor.

The copyable_function cannot be constructed from move_only_function, as it requires functor to be copyable. Invkoing an empty std::function has well defined behavior (throws bad_function_call), and wrapping such object into other functors should reproduce that behavior

Proposed resolution:

This wording is relative to N5008.

  1. Modify 22.10.17.1 [func.wrap.general] as indicated:

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

    -8- Postconditions:: *this has no target object if any of the following hold:

    • (8.1) f is a null function pointer value, or

    • (8.2) f is a null member pointer value, or

    • (8.2) remove_cvref_t<F> is a specialization of the move_only_function or copyable_function class template, and f has no target object.