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>

Reply via email to