https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119125
--- Comment #1 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Tomasz Kaminski <tkami...@gcc.gnu.org>: https://gcc.gnu.org/g:708d40ff109c6e49d02b684a368571722a160af8 commit r16-617-g708d40ff109c6e49d02b684a368571722a160af8 Author: Tomasz KamiÅski <tkami...@redhat.com> Date: Thu May 8 08:08:43 2025 +0200 libstdc++: Avoid double indirection in move_only_function when possible [PR119125] Based on the provision in C++26 [func.wrap.general] p2 this patch adjust the generic move_only_function(_Fn&&) constructor, such that when _Fn refers to selected move_only_function instantiations, the ownership of the target object is directly transfered to constructor object. This avoid cost of double indirection in this situation. We apply this also in C++23 mode. We also fix handling of self assignments, to match behavior required by standard, due use of copy and swap idiom. An instantiations MF1 of move_only_function can transfer target of another instantiation MF2, if it can be constructed via usual rules (__is_callable_from<_MF2>), and their invoker are convertible (__is_invoker_convertible<MF2, MF1>()), i.e.: * MF1 is less noexcept than MF2, * return types are the same after stripping cv-quals, * adujsted parameters type are the same (__poly::_param_t), i.e. param of types T and T&& are compatible for non-trivially copyable objects. Compatiblity of cv ref qualification is checked via __is_callable_from<_MF2>. To achieve above the generation of _M_invoke functions is moved to _Invoker class templates, that only depends on noexcept, return type and adjusted parameter of the signature. To make the invoker signature compatible between const and mutable qualified signatures, we always accept _Storage as const& and perform a const_cast for locally stored object. This approach guarantees that we never strip const from const object. Another benefit of this approach is that move_only_function<void(std::string)> and move_only_function<void(std::string&&)> use same funciton pointer, which should reduce binary size. The _Storage and _Manager functionality was also extracted and adjusted from _Mofunc_base, in preparation for implementation for copyable_function and function_ref. The _Storage was adjusted to store functions pointers as void(*)(). The manage function, now accepts _Op enum parameter, and supports additional operations: * _Op::_Address stores address of target object in destination * _Op::_Copy, when enabled, copies from source to destination Furthermore, we provide a type-independent mamange functions for handling all: * function pointer types * trivially copyable object stored locally. Similary as in case of invoker, we always pass source as const (for copy), and cast away constness in case of move operations, where we know that source is mutable. Finally, the new helpers are defined in __polyfunc internal namespace. PR libstdc++/119125 libstdc++-v3/ChangeLog: * include/bits/mofunc_impl.h: (std::move_only_function): Adjusted for changes in bits/move_only_function.h (move_only_function::move_only_function(_Fn&&)): Special case move_only_functions with same invoker. (move_only_function::operator=(move_only_function&&)): Handle self assigment. * include/bits/move_only_function.h (__polyfunc::_Ptrs) (__polyfunc::_Storage): Refactored from _Mo_func::_Storage. (__polyfunc::__param_t): Moved from move_only_function::__param_t. (__polyfunc::_Base_invoker, __polyfunc::_Invoke): Refactored from move_only_function::_S_invoke. (__polyfunc::_Manager): Refactored from _Mo_func::_S_manager. (std::_Mofunc_base): Moved into __polyfunc::_Mo_base with parts extracted to __polyfunc::_Storage and __polyfunc::_Manager. (__polyfunc::__deref_as, __polyfunc::__invoker_of) (__polyfunc::__base_of, __polyfunc::__is_invoker_convertible): Define. (std::__is_move_only_function_v): Renamed to __is_polymorphic_function_v. (std::__is_polymorphic_function_v): Renamed from __is_move_only_function_v. * testsuite/20_util/move_only_function/call.cc: Test for functions pointers. * testsuite/20_util/move_only_function/conv.cc: New test. * testsuite/20_util/move_only_function/move.cc: Tests for self assigment. Reviewed-by: Jonathan Wakely <jwak...@redhat.com> Signed-off-by: Tomasz KamiÅski <tkami...@redhat.com>