<functional>: Avoid double wrapping in move_only_function construction (original) (raw)

WG21-P2548R6 relaxed some requirements for polymorphic function wrappers by adding wording in [func.wrap.general].

  1. Let t be an object of a type that is a specialization of function, copyable_function, or move_only_function, such that the target object x of t has a type that is a specialization of function, copyable_function, or move_only_function. Each argument of the invocation of x evaluated as part of the invocation of t may alias an argument in the same position in the invocation of t that has the same type, even if the corresponding parameter is not of reference type.

[Example 1:

move_only_function<void(T)> f{copyable_function<void(T)>{ {}}}; T t; f(t); // it is unspecified how many copies of T are made

— _end example_]

  1. Recommended practice: Implementations should avoid double wrapping when constructing polymorphic wrappers from one another.

However, if I understand correctly, we can't avoid double wrapping in construction of function, even in vNext, because it's target object is observable via the target member function.

For move_only_function and copyable_function, it seems possible to unwrap in construction, because the target object is not observable and thus can be non-existent under some conditions.

I think its better to treat the allowance as a DR against C++23 (i.e. to implement it for move_only_function unconditionally), because that is ABI-critical and libstdc++ starts doing so recently.

Personal concerns: