WG21-P2548R6 relaxed some requirements for polymorphic function wrappers by adding wording in [func.wrap.general].
- 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 t;
f(t); // it is unspecified how many copies of T are made
— end example]
- 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:
- When constructing a
move_only_function from an empty function, we need to keep the throwing-on-invocation behavior, which means that the constructed move_only_function can't be empty.
- It might be better to recognize program-defined specializations and avoid invalid unwrapping for them. But since support for program-defined specializations of
function is already broken, and the program-defined specializations can hardly be helpful, it might be also plausible not to do this.
WG21-P2548R6 relaxed some requirements for polymorphic function wrappers by adding wording in [func.wrap.general].
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 thetargetmember function.For
move_only_functionandcopyable_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_functionunconditionally), because that is ABI-critical and libstdc++ starts doing so recently.Personal concerns:
move_only_functionfrom an emptyfunction, we need to keep the throwing-on-invocation behavior, which means that the constructedmove_only_functioncan't be empty.functionis already broken, and the program-defined specializations can hardly be helpful, it might be also plausible not to do this.