libstdc++: Implement C++26 function_ref [PR119126]
This patch implements C++26 function_ref as specified in P0792R14,
with correction for constraints for constructor accepting nontype_t
parameter from LWG 4256.
As function_ref may store a pointer to the const object, __Ptrs::_M_obj is
changed to const void*, so again we do not cast away const from const
objects. To help with necessary casts, a __polyfunc::__cast_to helper is
added, that accepts reference to or target type direclty.
The _Invoker now defines additional call methods used by function_ref:
_S_ptrs() for invoking target passed by reference, and __S_nttp, _S_bind_ptr,
_S_bind_ref for handling constructors accepting nontype_t. The existing
_S_call_storage is changed to thin wrapper, that initialies _Ptrs, and forwards
to _S_call_ptrs.
This reduced the most uses of _Storage::_M_ptr and _Storage::_M_ref,
so this functions was removed, and _Manager uses were adjusted.
Finally we make function_ref available in freestanding mode, as
move_only_function and copyable_function are currently only available in hosted,
so we define _Manager and _Mo_base only if either __glibcxx_move_only_function
or __glibcxx_copyable_function is defined.
PR libstdc++/119126
libstdc++-v3/ChangeLog:
* doc/doxygen/stdheader.cc: Added funcref_impl.h file.
* include/Makefile.am: Added funcref_impl.h file.
* include/Makefile.in: Added funcref_impl.h file.
* include/bits/funcref_impl.h: New file.
* include/bits/funcwrap.h: (_Ptrs::_M_obj): Const-qualify.
(_Storage::_M_ptr, _Storage::_M_ref): Remove.
(__polyfunc::__cast_to) Define.
(_Base_invoker::_S_ptrs, _Base_invoker::_S_nttp)
(_Base_invoker::_S_bind_ptrs, _Base_invoker::_S_bind_ref)
(_Base_invoker::_S_call_ptrs): Define.
(_Base_invoker::_S_call_storage): Foward to _S_call_ptrs.
(_Manager::_S_local, _Manager::_S_ptr): Adjust for _M_obj being
const qualified.
(__polyfunc::_Manager, __polyfunc::_Mo_base): Guard with
__glibcxx_move_only_function || __glibcxx_copyable_function.
(__polyfunc::__skip_first_arg, __polyfunc::__deduce_funcref)
(std::function_ref) [__glibcxx_function_ref]: Define.
* include/bits/utility.h (std::nontype_t, std::nontype)
(__is_nontype_v) [__glibcxx_function_ref]: Define.
* include/bits/version.def: Define function_ref.
* include/bits/version.h: Regenerate.
* include/std/functional: Define __cpp_lib_function_ref.
* src/c++23/std.cc.in (std::nontype_t, std::nontype)
(std::function_ref) [__cpp_lib_function_ref]: Export.
* testsuite/20_util/function_ref/assign.cc: New test.
* testsuite/20_util/function_ref/call.cc: New test.
* testsuite/20_util/function_ref/cons.cc: New test.
* testsuite/20_util/function_ref/cons_neg.cc: New test.
* testsuite/20_util/function_ref/conv.cc: New test.
* testsuite/20_util/function_ref/deduction.cc: New test.
* testsuite/20_util/function_ref/mutation.cc: New test.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-14 12:04:24 +02:00
|
|
|
// Implementation of std::move_only_function, std::copyable_function
|
|
|
|
|
// and std::function_ref -*- C++ -*-
|
2021-10-06 13:28:57 +01:00
|
|
|
|
|
|
|
|
// Copyright The GNU Toolchain Authors.
|
|
|
|
|
//
|
|
|
|
|
// This file is part of the GNU ISO C++ Library. This library is free
|
|
|
|
|
// software; you can redistribute it and/or modify it under the
|
|
|
|
|
// terms of the GNU General Public License as published by the
|
|
|
|
|
// Free Software Foundation; either version 3, or (at your option)
|
|
|
|
|
// any later version.
|
|
|
|
|
|
|
|
|
|
// This library is distributed in the hope that it will be useful,
|
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
// Under Section 7 of GPL version 3, you are granted additional
|
|
|
|
|
// permissions described in the GCC Runtime Library Exception, version
|
|
|
|
|
// 3.1, as published by the Free Software Foundation.
|
|
|
|
|
|
|
|
|
|
// You should have received a copy of the GNU General Public License and
|
|
|
|
|
// a copy of the GCC Runtime Library Exception along with this program;
|
|
|
|
|
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
|
|
|
|
// <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
2025-05-12 11:06:34 +02:00
|
|
|
/** @file include/bits/funcwrap.h
|
2021-10-06 13:28:57 +01:00
|
|
|
* This is an internal header file, included by other library headers.
|
|
|
|
|
* Do not attempt to use it directly. @headername{functional}
|
|
|
|
|
*/
|
|
|
|
|
|
2025-05-12 11:06:34 +02:00
|
|
|
#ifndef _GLIBCXX_FUNCWRAP_H
|
|
|
|
|
#define _GLIBCXX_FUNCWRAP_H 1
|
2021-10-06 13:28:57 +01:00
|
|
|
|
2024-09-12 12:15:51 -04:00
|
|
|
#ifdef _GLIBCXX_SYSHDR
|
2021-10-06 13:28:57 +01:00
|
|
|
#pragma GCC system_header
|
2024-09-12 12:15:51 -04:00
|
|
|
#endif
|
2021-10-06 13:28:57 +01:00
|
|
|
|
libstdc++: Replace all manual FTM definitions and use
libstdc++-v3/ChangeLog:
* libsupc++/typeinfo: Switch to bits/version.h for
__cpp_lib_constexpr_typeinfo.
* libsupc++/new: Switch to bits/version.h for
__cpp_lib_{launder,hardware_interference_size,destroying_delete}.
(launder): Guard behind __cpp_lib_launder.
(hardware_destructive_interference_size)
(hardware_constructive_interference_size): Guard behind
__cpp_lib_hardware_interference_size.
* libsupc++/exception: Switch to bits/version.h for
__cpp_lib_uncaught_exceptions.
(uncaught_exceptions): Guard behind __cpp_lib_uncaught_exceptions.
* libsupc++/compare: Switch to bits/version.h for
__cpp_lib_three_way_comparison.
(three_way_comparable, three_way_comparable_with)
(compare_three_way, weak_order, strong_order, partial_order):
Guard behind __cpp_lib_three_way_comparison >= 201907L.
* include/std/chrono: Drop __cpp_lib_chrono definition.
* include/std/vector: Switch to bits/version.h for
__cpp_lib_erase_if.
(erase, erase_if): Guard behind __cpp_lib_erase_if.
* include/std/variant: Switch to bits/version.h for
__cpp_lib_variant. Guard whole header behind that FTM.
* include/std/utility: Switch to bits/version.h for
__cpp_lib_{exchange_function,constexpr_algorithms,as_const},
__cpp_lib_{integer_comparison_functions,to_underlying}, and
__cpp_lib_unreachable.
(exchange): Guard behind __cpp_lib_exchange_function.
(cmp_equal, cmp_not_equal, cmp_less, cmp_greater, cmp_less_equal)
(cmp_greater_equal, in_range): Guard behind
__cpp_lib_integer_comparison_functions.
(to_underlying): Guard behind __cpp_lib_to_underlying.
(unreachable): Guard behind __cpp_lib_unreachable.
* include/std/type_traits: Switch to bits/version.h for
__cpp_lib_is_{null_pointer,final,nothrow_convertible,aggregate},
__cpp_lib_is_{constant_evaluated,invocable,layout_compatible},
__cpp_lib_is_{pointer_interconvertible,scoped_enum,swappable},
__cpp_lib_{logical_traits,reference_from_temporary,remove_cvref},
__cpp_lib_{result_of_sfinae,transformation_trait_aliases},
__cpp_lib_{type_identity,type_trait_variable_templates},
__cpp_lib_{unwrap_ref,void_t,integral_constant_callable},
__cpp_lib_{bool_constant,bounded_array_traits}, and
__cpp_lib_has_unique_object_representations.
(integral_constant::operator()): Guard behind
__cpp_lib_integral_constant_callable.
(bool_constant): Guard behind __cpp_lib_bool_constant.
(conjunction, disjunction, negation, conjunction_v, disjunction_v)
(negation_v): Guard behind __cpp_lib_logical_traits.
(is_null_pointer): Guard behind __cpp_lib_is_null_pointer.
(is_final): Guard behind __cpp_lib_is_final.
(is_nothrow_convertible, is_nothrow_convertible_v): Guard behind
__cpp_lib_is_nothrow_convertible.
(remove_const_t, remove_volatile_t, remove_cv_t)
(add_const_t, add_volatile_t, add_cv_t): Guard behind
__cpp_lib_transformation_trait_aliases.
(void_t): Guard behind __cpp_lib_void_t.
(is_swappable_with_v, is_nothrow_swappable_with_v)
(is_swappable_with, is_nothrow_swappable_with): Guard behind
__cpp_lib_is_swappable.
(is_nothrow_invocable_r, is_invocable_r, invoke_result)
(is_invocable, invoke_result_t): Guard behind
__cpp_lib_is_invocable.
(alignment_of_v, extent_v, has_virtual_destructor_v)
(is_abstract_v, is_arithmetic_v, is_array_v)
(is_assignable_v, is_base_of_v, is_class_v, is_compound_v)
(is_constructible_v, is_const_v, is_convertible_v)
(is_copy_assignable_v, is_copy_constructible_v)
(is_default_constructible_v, is_destructible_v)
(is_empty_v, is_enum_v, is_final_v, is_floating_point_v)
(is_function_v, is_fundamental_v, is_integral_v)
(is_invocable_r_v, is_invocable_v, is_literal_type_v)
(is_lvalue_reference_v, is_member_function_pointer_v)
(is_member_object_pointer_v, is_member_pointer_v)
(is_move_assignable_v, is_move_constructible_v)
(is_nothrow_assignable_v, is_nothrow_constructible_v)
(is_nothrow_copy_assignable_v, is_nothrow_copy_constructible_v)
(is_nothrow_default_constructible_v, is_nothrow_destructible_v)
(is_nothrow_invocable_r_v, is_nothrow_invocable_v)
(is_nothrow_move_assignable_v, is_nothrow_move_constructible_v)
(is_null_pointer_v, is_object_v, is_pod_v, is_pointer_v)
(is_polymorphic_v, is_reference_v, is_rvalue_reference_v)
(is_same_v, is_scalar_v, is_signed_v, is_standard_layout_v)
(is_trivially_assignable_v, is_trivially_constructible_v)
(is_trivially_copyable_v, is_trivially_copy_assignable_v)
(is_trivially_copy_constructible_v)
(is_trivially_default_constructible_v)
(is_trivially_destructible_v, is_trivially_move_assignable_v)
(is_trivially_move_constructible_v, is_trivial_v, is_union_v)
(is_unsigned_v, is_void_v, is_volatile_v, rank_v, as variadic):
Guard behind __cpp_lib_type_trait_variable_templates.
(has_unique_object_representations)
(has_unique_object_representations_v): Guard behind
__cpp_lib_has_unique_object_representation.
(is_aggregate): Guard behind __cpp_lib_is_aggregate.
(remove_cvref, remove_cvref_t): Guard behind
__cpp_lib_remove_cvref.
(type_identity, type_identity_t): Guard behind
__cpp_lib_type_identity.
(unwrap_reference, unwrap_reference_t, unwrap_ref_decay)
(unwrap_ref_decay_t): Guard behind __cpp_lib_unwrap_ref.
(is_bounded_array_v, is_unbounded_array_v, is_bounded_array)
(is_unbounded_array): Guard behind __cpp_lib_bounded_array_traits.
(is_scoped_enum, is_scoped_enum_v): Guard behind
__cpp_lib_is_scoped_enum.
(reference_constructs_from_temporary)
(reference_constructs_from_temporary_v): Guard behind
__cpp_lib_reference_from_temporary.
* include/std/tuple: Switch to bits/version.h for
__cpp_lib_{constexpr_tuple,tuple_by_type,apply_make_from_tuple}.
(get<T>): Guard behind __cpp_lib_tuple_by_type.
(apply): Guard behind __cpp_lib_apply.
(make_from_tuple): Guard behind __cpp_lib_make_from_tuple.
* include/std/syncstream: Switch to bits/version.h for
__cpp_lib_syncbuf. Guard header behind that FTM.
* include/std/string_view: Switch to bits/version.h for
__cpp_lib_{string_{view,contains},constexpr_string_view} and
__cpp_lib_starts_ends_with.
(basic_string_view::starts_with, basic_string_view::ends_with):
Guard behind __cpp_lib_starts_ends_with.
[C++23 && _GLIBCXX_HOSTED && !defined(__cpp_lib_string_contains)]:
Assert as impossible ithout a bug in C++23.
* include/std/string: Switch to bits/version.h for
__cpp_lib_erase_if.
(erase, erase_if): Guard behind __cpp_lib_erase_if.
* include/std/thread: Switch to bits/version.h for
__cpp_lib_jthread.
* include/std/stop_token: Switch to bits/version.h for
__cpp_lib_jthread.
* include/std/spanstream: Switch to bits/version.h for
__cpp_lib_spanstream. Guard header behind that FTM.
* include/std/span: Switch to bits/version.h for __cpp_lib_span.
Guard header behind that FTM.
* include/std/source_location: Switch to bits/version.h for
__cpp_lib_source_location. Guard header with that FTM.
* include/std/shared_mutex: Switch to bits/version.h for
__cpp_lib_shared{,_timed}_mutex.
(shared_mutex): Guard behind __cpp_lib_shared_mutex.
* include/std/semaphore: Switch to bits/version.h for
__cpp_lib_semaphore. Guard header behind that FTM.
* include/std/ranges: Switch to bits/version.h for
__cpp_lib_ranges_{zip,chunk{,_by},slide,join_with},
__cpp_lib_ranges_{repeat_stride,cartesian_product,as_rvalue},
and __cpp_lib_ranges_{as_const,enumerate,iota}.
(ranges::zip et al, ranges::chunk et al, ranges::slide et al)
(ranges::chunk_by et al, ranges::join_with et al)
(ranges::stride et al, ranges::cartesian_product et al)
(ranges::as_rvalue et al, ranges::as_const et al)
(ranges::enumerate et al): Guard behind appropriate FTM.
* include/std/optional: Switch to bits/version.h for
__cpp_lib_optional. Guard header behind that FTM.
* include/std/numeric: Switch to bits/version.h for
__cpp_lib_{gcd{,_lcm},lcm,constexpr_numeric,interpolate}
and __cpp_lib_parallel_algorithm.
(gcd, lcm): Guard behind __cpp_lib_gcd_lcm.
(midpoint): Guard behind __cpp_lib_interpolate.
* include/std/numbers: Switch to bits/version.h for
__cpp_lib_math_constants. Guard header behind that FTM.
* include/std/mutex: Switch to bits/version.h for
__cpp_lib_scoped_lock.
(scoped_Lock): Guard behind __cpp_lib_scoped_lock.
* include/std/memory_resource: Switch to bits/version.h for
__cpp_lib_{polymorphic_allocator,memory_resource}.
(synchronized_pool_resource): Guard behind
__cpp_lib_memory_resource >= 201603L.
(polymorphic_allocator): Guard behind
__cpp_lib_polymorphic_allocator.
* include/std/memory: Switch to bits/version.h for
__cpp_lib_{parallel_algorithm,atomic_value_initialization}.
* include/std/list: Switch to bits/version.h for
__cpp_lib_erase_if.
(erase, erase_if): Guard behind __cpp_lib_erase_if.
* include/std/latch: Switch to bits/version.h for __cpp_lib_latch.
Guard header behind that FTM.
* include/std/iterator: Switch to bits/version.h for
__cpp_lib_null_iterators.
* include/std/iomanip: Switch to bits/version.h for
__cpp_lib_quoted_string_io.
(quoted): Guard behind __cpp_lib_quoted_string_io.
* include/std/functional: Switch to bits/version.h for
__cpp_lib_{invoke{,_r},constexpr_functional,bind_front} and
__cpp_lib_{not_fn,booyer_moore_searcher}.
(invoke): Guard behind __cpp_lib_invoke.
(invoke_r): Guard behind __cpp_lib_invoke_r.
(bind_front): Guard behind __cpp_lib_bind_front.
(not_fn): Guard behind __cpp_lib_not_fn.
(boyer_moore_searcher, boyer_moore_horspool_searcher): Guard
definition behind __cpp_lib_boyer_moore_searcher.
* include/std/forward_list: Switch to bits/version.h for
__cpp_lib_erase_if.
(erase, erase_if): Guard behind __cpp_lib_erase_if.
* include/std/format: Switch to bits/version.h for
__cpp_lib_format. Guard header behind that FTM.
* include/std/filesystem: Switch to bits/version.h for
__cpp_lib_filesystem. Guard header behind that FTM.
* include/std/expected: Switch to bits/version.h for
__cpp_lib_expected. Guard header behind it.
* include/std/execution: Switch to bits/version.h for
__cpp_lib_{execution,parallel_algorithm}. Guard header behind
either.
* include/std/deque: Switch to bits/version.h for
__cpp_lib_erase_if.
(erase, erase_if): Guard behind __cpp_lib_erase_if.
* include/std/coroutine: Switch to bits/version.h for
__cpp_lib_coroutine. Guard header behind that FTM.
* include/std/concepts: Switch to bits/version.h for
__cpp_lib_concepts. Guard header behind that FTM.
* include/std/complex: Switch to bits/version.h for
__cpp_lib_{complex_udls,constexpr_complex}.
(operator""if, operator""i, operator""il): Guard behind
__cpp_lib_complex_udls.
* include/std/charconv: Swtich to bits/version.h for
__cpp_lib_{to_chars,constexpr_charconv}.
* include/std/bitset: Switch to bits/version.h for
__cpp_lib_constexpr_bitset.
* include/std/bit: Switch to bits/version.h for
__cpp_lib_{bit_cast,byteswap,bitops,int_pow2,endian}.
(bit_cast): Guard behind __cpp_lib_bit_cast.
(byteswap): Guard behind __cpp_lib_byteswap.
(rotl, rotr, countl_zero, countl_one, countr_zero, countr_one)
(popcount): Guard behind __cpp_lib_bitops.
(has_single_bit, bit_ceil, bit_floor, bit_width): Guard behind
__cpp_lib_int_pow2.
(endian): Guard behind __cpp_lib_endian.
* include/std/barrier: Switch to bits/version.h for
__cpp_lib_barrier. Guard header behind that FTM.
* include/std/atomic: Switch to bits/version.h for
__cpp_lib_atomic_{is_always_lock_free,float,ref}
and __cpp_lib_lock_free_type_aliases.
(*::is_always_lock_free): Guard behind
__cpp_lib_atomic_is_always_lock_free.
(atomic<float>): Guard behind __cpp_lib_atomic_float.
(atomic_ref): Guard behind __cpp_lib_atomic_ref.
(atomic_signed_lock_free, atomic_unsigned_lock_free): Guard behind
__cpp_lib_atomic_lock_free_type_aliases.
* include/std/array: Switch to bits/version.h for
__cpp_lib_to_array.
(to_array): Guard behind __cpp_lib_to_array.
* include/std/any: Switch to bits/version.h for __cpp_lib_any.
Guard header behind that FTM.
* include/std/algorithm: Switch to bits/version.h for
__cpp_lib_parallel_algorithm.
* include/c_global/cstddef: Switch to bits/version.h for
__cpp_lib_byte.
(byte): Guard behind __cpp_lib_byte.
* include/c_global/cmath: Switch to bits/version.h for
__cpp_lib_{hypot,interpolate}.
(hypot3): Guard behind __cpp_lib_hypot.
(lerp): Guard behind __cpp_lib_interpolate.
* include/c_compatibility/stdatomic.h: Switch to
bits/stl_version.h for __cpp_lib_atomic. Guard header behind that
FTM.
* include/bits/utility.h: Switch to bits/version.h for
__cpp_lib_{tuple_element_t,integer_sequence,ranges_zip}.
(tuple_element_t): Guard behind __cpp_lib_tuple_element_t.
(integer_sequence et al): Guard behind __cpp_lib_integer_sequence.
* include/bits/uses_allocator_args.h: Switch to bits/version.h for
__cpp_lib_make_obj_using_allocator. Guard header behind that FTM.
* include/bits/unordered_map.h: Switch to bits/version.h for
__cpp_lib_unordered_map_try_emplace.
(try_emplace): Guard behind __cpp_lib_unordered_map_try_emplace.
* include/bits/unique_ptr.h: Switch to bits/version.h for
__cpp_lib_{constexpr_memory,make_unique}.
(make_unique): Guard behind __cpp_lib_make_unique.
* include/bits/stl_vector.h: Switch to bits/version.h for
__cpp_lib_constexpr_vector.
* include/bits/stl_uninitialized.h: Switch to bits/version.h for
__cpp_lib_raw_memory_algorithms.
(uninitialized_default_construct)
(uninitialized_default_construct_n, uninitialized_move)
(uninitialized_move_n, uninitialized_value_construct)
(uninitialized_value_construct_n): Guard behind
__cpp_lib_raw_memory_algorithms.
* include/bits/stl_tree.h: Switch to bits/version.h for
__cpp_lib_generic_associative_lookup.
* include/bits/stl_stack.h: Switch to bits/version.h for
__cpp_lib_adaptor_iterator_pair_constructor.
(stack): Guard iterator-pair constructor behind
__cpp_lib_adaptor_iterator_pair_constructor.
* include/bits/stl_queue.h: Switch to bits/version.h for
__cpp_lib_adaptor_iterator_pair_constructor.
(queue): Guard iterator-pair constructor behind
__cpp_lib_adaptor_iterator_pair_constructor.
* include/bits/stl_pair.h: Switch to bits/version.h for
__cpp_lib_{concepts,tuples_by_type}.
(get): Guard type-getting overloads behind
__cpp_lib_tuples_by_type.
* include/bits/stl_map.h: Switch to bits/version.h for
__cpp_lib_map_try_emplace.
(map<>::try_emplace): Guard behind __cpp_lib_map_try_emplace.
* include/bits/stl_list.h: Switch to bits/version.h for
__cpp_lib_list_remove_return_type.
(__remove_return_type, _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG)
[C++20]: guard behind __cpp_lib_list_remove_return_type instead.
* include/bits/stl_iterator.h: Switch to bits/version.h for
__cpp_lib_{constexpr_iterator,array_constexpr} and
__cpp_lib_{make_reverse_iterator,move_iterator_concept}.
(make_reverse_iterator): Guard behind
__cpp_lib_make_reverse_iterator.
(iterator_concept et al): Guard __cpp_lib_move_iterator_concept
changes behind that FTM.
* include/bits/stl_function.h: Switch to bits/version.h for
__cpp_lib_transparent_operators.
(equal_to, not_equal_to, greater, less, greater_equal)
(less_equal, bit_and, bit_or, bit_xor, bit_not, logical_and)
(logical_or, logical_not, plus, minus, multiplies, divides)
(modulus, negate): Guard '= void' fwdecls behind
__cpp_lib_transparent_operators.
(plus<void>, minus<void>, multiplies<void>, divides<void>)
(modulus<void>, negate<void>, logical_and<void>, logical_or<void>)
(logical_not<void>, bit_and<void>, bit_or<void>, bit_xor<void>)
(equal_to<void>, not_equal_to<void>, greater<void>, less<void>)
(greater_equal<void>, less_equal<void>, bit_not<void>)
(__has_is_transparent): Guard behind
__cpp_lib_transparent_operators.
* include/bits/stl_algobase.h: Switch to bits/version.h for
__cpp_lib_robust_nonmodifying_seq_ops.
(robust equal, mismatch): Guard behind
__cpp_lib_nonmember_container_access.
* include/bits/stl_algo.h: Swtich to bits/version.h for
__cpp_lib_{clamp,sample}.
(clamp): Guard behind __cpp_lib_clamp.
(sample): Guard behind __cpp_lib_sample.
* include/bits/specfun.h: Switch to bits/version.h for
__cpp_lib_math_special_functions and __STDCPP_MATH_SPEC_FUNCS__.
* include/bits/shared_ptr_base.h: Switch to bits/version.h for
__cpp_lib_{smart_ptr_for_overwrite,shared_ptr_arrays}.
(_Sp_overwrite_tag): Guard behind
__cpp_lib_smart_ptr_for_overwrite.
* include/bits/shared_ptr_atomic.h: Switch to bits/version.h for
__cpp_lib_atomic_shared_ptr.
* include/bits/shared_ptr.h: Switch to bits/version.h for
__cpp_lib_{enable_shared_from_this,shared_ptr_weak_type}.
(shared_ptr<T>::weak_type): Guard behind
__cpp_lib_shared_ptr_weak_type.
(enable_shared_from_this<T>::weak_from_this): Guard behind
__cpp_lib_enable_shared_from_this.
* include/bits/ranges_cmp.h: Switch to bits/version.h for
__cpp_lib_ranges.
* include/bits/ranges_algo.h: Switch to bits/version.h for
__cpp_lib_{shift,ranges_{contains,find_last,fold,iota}}.
* include/bits/range_access.h: Switch to bits/version.h for
__cpp_lib_nonmember_container_access
(size, empty, data): Guard behind
__cpp_lib_nonmember_container_access.
(ssize): Guard behind __cpp_lib_ssize.
* include/bits/ptr_traits.h: Switch to bits/version.h. for
__cpp_lib_{constexpr_memory,to_address}.
(to_address): Guard behind __cpp_lib_to_address.
* include/bits/node_handle.h: Switch to bits/version.h for
__cpp_lib_node_extract. Guard header behind that FTM.
* include/bits/move_only_function.h: Switch to bits/version.h for
__cpp_lib_move_only_function. Guard header behind that FTM.
* include/bits/move.h: Switch to bits/version.h for
__cpp_lib_addressof_constexpr.
* include/bits/ios_base.h: Switch to bits/version.h for
__cpp_lib_ios_noreplace.
(noreplace): Guard with __cpp_lib_ios_noreplace.
* include/bits/hashtable.h: Switch to bits/version.h for
__cpp_lib_generic_unordered_lookup.
(_M_equal_range_tr, _M_count_tr, _M_find_tr): Guard behind
__cpp_lib_generic_unordered_lookup.
* include/bits/forward_list.h: Switch to bits/version.h for
__cpp_lib_list_remove_return_type.
(__remove_return_type): Guard behind
__cpp_lib_list_remove_return_type.
* include/bits/erase_if.h: Switch to bits/version.h for
__cpp_lib_erase_if.
* include/bits/cow_string.h: Switch to bits/version.h for
__cpp_lib_constexpr_string.
* include/bits/chrono.h: Swtich to bits/version.h for
__cpp_lib_chrono{,_udls}.
(ceil): Guard behind __cpp_lib_chrono.
(operator""ns et al): Guard behind __cpp_lib_chrono_udls.
* include/bits/char_traits.h: Switch to bits/version.h for
__cpp_lib_constexpr_char_traits.
* include/bits/basic_string.h: Switch to bits/version.h for
__cpp_lib_{constexpr_string,string_{resize_and_overwrite,udls}}.
(resize_and_overwrite): Guard behind
__cpp_lib_string_resize_and_overwrite.
(operator""s): Guard behind __cpp_lib_string_udls.
* include/bits/atomic_wait.h: Switch to bits/version.h for
__cpp_lib_atomic_wait. Guard header behind that FTM.
* include/bits/atomic_base.h: Switch to bits/version.h for
__cpp_lib_atomic_value_initialization and
__cpp_lib_atomic_flag_test.
(atomic_flag::test): Guard behind __cpp_lib_atomic_flag_test,
rather than C++20.
* include/bits/allocator.h: Switch to bits/version.h for
__cpp_lib_incomplete_container_elements.
* include/bits/alloc_traits.h: Switch to using bits/version.h for
__cpp_lib_constexpr_dynamic_alloc and
__cpp_lib_allocator_traits_is_always_equal.
* include/bits/align.h: Switch to bits/version.h for defining
__cpp_lib_assume_aligned.
(assume_aligned): Guard with __cpp_lib_assume_aligned.
* include/bits/algorithmfwd.h: Switch to bits/version.h for
defining __cpp_lib_constexpr_algorithms.
* include/std/stacktrace: Switch to bits/version.h for
__cpp_lib_stacktrace. Guard header behind that FTM.
* testsuite/23_containers/array/tuple_interface/get_neg.cc:
Update line numbers.
2023-04-27 21:03:15 +02:00
|
|
|
#include <bits/version.h>
|
|
|
|
|
|
libstdc++: Implement C++26 function_ref [PR119126]
This patch implements C++26 function_ref as specified in P0792R14,
with correction for constraints for constructor accepting nontype_t
parameter from LWG 4256.
As function_ref may store a pointer to the const object, __Ptrs::_M_obj is
changed to const void*, so again we do not cast away const from const
objects. To help with necessary casts, a __polyfunc::__cast_to helper is
added, that accepts reference to or target type direclty.
The _Invoker now defines additional call methods used by function_ref:
_S_ptrs() for invoking target passed by reference, and __S_nttp, _S_bind_ptr,
_S_bind_ref for handling constructors accepting nontype_t. The existing
_S_call_storage is changed to thin wrapper, that initialies _Ptrs, and forwards
to _S_call_ptrs.
This reduced the most uses of _Storage::_M_ptr and _Storage::_M_ref,
so this functions was removed, and _Manager uses were adjusted.
Finally we make function_ref available in freestanding mode, as
move_only_function and copyable_function are currently only available in hosted,
so we define _Manager and _Mo_base only if either __glibcxx_move_only_function
or __glibcxx_copyable_function is defined.
PR libstdc++/119126
libstdc++-v3/ChangeLog:
* doc/doxygen/stdheader.cc: Added funcref_impl.h file.
* include/Makefile.am: Added funcref_impl.h file.
* include/Makefile.in: Added funcref_impl.h file.
* include/bits/funcref_impl.h: New file.
* include/bits/funcwrap.h: (_Ptrs::_M_obj): Const-qualify.
(_Storage::_M_ptr, _Storage::_M_ref): Remove.
(__polyfunc::__cast_to) Define.
(_Base_invoker::_S_ptrs, _Base_invoker::_S_nttp)
(_Base_invoker::_S_bind_ptrs, _Base_invoker::_S_bind_ref)
(_Base_invoker::_S_call_ptrs): Define.
(_Base_invoker::_S_call_storage): Foward to _S_call_ptrs.
(_Manager::_S_local, _Manager::_S_ptr): Adjust for _M_obj being
const qualified.
(__polyfunc::_Manager, __polyfunc::_Mo_base): Guard with
__glibcxx_move_only_function || __glibcxx_copyable_function.
(__polyfunc::__skip_first_arg, __polyfunc::__deduce_funcref)
(std::function_ref) [__glibcxx_function_ref]: Define.
* include/bits/utility.h (std::nontype_t, std::nontype)
(__is_nontype_v) [__glibcxx_function_ref]: Define.
* include/bits/version.def: Define function_ref.
* include/bits/version.h: Regenerate.
* include/std/functional: Define __cpp_lib_function_ref.
* src/c++23/std.cc.in (std::nontype_t, std::nontype)
(std::function_ref) [__cpp_lib_function_ref]: Export.
* testsuite/20_util/function_ref/assign.cc: New test.
* testsuite/20_util/function_ref/call.cc: New test.
* testsuite/20_util/function_ref/cons.cc: New test.
* testsuite/20_util/function_ref/cons_neg.cc: New test.
* testsuite/20_util/function_ref/conv.cc: New test.
* testsuite/20_util/function_ref/deduction.cc: New test.
* testsuite/20_util/function_ref/mutation.cc: New test.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-14 12:04:24 +02:00
|
|
|
#if __glibcxx_move_only_function || __glibcxx_copyable_function || __glibcxx_function_ref
|
2021-10-06 13:28:57 +01:00
|
|
|
|
|
|
|
|
#include <bits/invoke.h>
|
|
|
|
|
#include <bits/utility.h>
|
libstdc++: Make function_ref non-dangling for stateless wrappers
This patch makes the function_ref non-dangling for the stateless
wrappers:
* any functor for which operator() selected for arguments is static,
* standard functors, including pre-C++20 ones.
In other words, any function_ref fr, that is constructed from stateless
wrapper w, can be still called after the object w is destroyed, e.g.:
std::function_ref<bool(int, int)> fr(std::ranges::less{});
fr(1, 2); // OK, previously UB because fr referred to already destroyed
// temporary
As function_ref's operator() is not constexpr, we test the change by checking
if the above declaration can be made constexpr, as such variable cannot contain
dangling pointer values.
We adjust the function_ref generic constructor from any functor, to use more
specialized invoker:
* _S_static (newly added) if the called operator() overload is static,
after changes r16-5624-g0ea9d760fbf44c, this covers all post-c++20 functors;
* _S_nttp<_Fd{}> for pre-C++20 standard functors.
In both above cases the value of _M_ptrs is ignored and simply set to nullptr.
This follows same technique (checking _Fd::operator()(args...)), and support
the same set of types, as for one used for the transform views iterators in
r16-5625-g9ed821d107f7a1.
As after this change we provide well-defined behavior for the code, that
previous was undefined, this changes is pure quality-of-implementation.
As illustrated by the test cases, it has observable side effects, where
non-longer dangling constructs can be used to define constexpr function_ref.
However, the standard does not define when the constructors defined constexpr
are actually usable at compile time, and the already have precedent in form
of SSO string for validity such constructs being implementation specific.
libstdc++-v3/ChangeLog:
* include/bits/funcref_impl.h (function_ref::function_ref(_Fn&&)):
Use _S_static and _S_nttp invokers.
* include/bits/funcwrap.h (_Base_invoker::_S_static):
Define.
* include/bits/stl_function.h (std::__is_std_op_template)
(std::__is_std_op_wrapper) [__cplusplus > 201703L]:
Moved from std/ranges.
* include/std/ranges (__detail::__is_std_op_template)
(__detail::__is_std_op_wrapper): Moved to bits/stl_function.h.
* testsuite/20_util/function_ref/dangling.cc: New test.
* testsuite/20_util/function_ref/dangling_neg.cc: New test.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2026-02-02 10:19:51 +01:00
|
|
|
#if __glibcxx_function_ref
|
|
|
|
|
#include <bits/stl_function.h>
|
|
|
|
|
#endif
|
2021-10-06 13:28:57 +01:00
|
|
|
|
|
|
|
|
namespace std _GLIBCXX_VISIBILITY(default)
|
|
|
|
|
{
|
|
|
|
|
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|
|
|
|
|
|
|
|
|
/// @cond undocumented
|
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 <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-08 08:08:43 +02:00
|
|
|
template<typename _Tp>
|
|
|
|
|
inline constexpr bool __is_polymorphic_function_v = false;
|
2021-10-06 13:28:57 +01:00
|
|
|
|
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 <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-08 08:08:43 +02:00
|
|
|
namespace __polyfunc
|
|
|
|
|
{
|
|
|
|
|
union _Ptrs
|
2021-10-06 13:28:57 +01:00
|
|
|
{
|
libstdc++: Implement C++26 function_ref [PR119126]
This patch implements C++26 function_ref as specified in P0792R14,
with correction for constraints for constructor accepting nontype_t
parameter from LWG 4256.
As function_ref may store a pointer to the const object, __Ptrs::_M_obj is
changed to const void*, so again we do not cast away const from const
objects. To help with necessary casts, a __polyfunc::__cast_to helper is
added, that accepts reference to or target type direclty.
The _Invoker now defines additional call methods used by function_ref:
_S_ptrs() for invoking target passed by reference, and __S_nttp, _S_bind_ptr,
_S_bind_ref for handling constructors accepting nontype_t. The existing
_S_call_storage is changed to thin wrapper, that initialies _Ptrs, and forwards
to _S_call_ptrs.
This reduced the most uses of _Storage::_M_ptr and _Storage::_M_ref,
so this functions was removed, and _Manager uses were adjusted.
Finally we make function_ref available in freestanding mode, as
move_only_function and copyable_function are currently only available in hosted,
so we define _Manager and _Mo_base only if either __glibcxx_move_only_function
or __glibcxx_copyable_function is defined.
PR libstdc++/119126
libstdc++-v3/ChangeLog:
* doc/doxygen/stdheader.cc: Added funcref_impl.h file.
* include/Makefile.am: Added funcref_impl.h file.
* include/Makefile.in: Added funcref_impl.h file.
* include/bits/funcref_impl.h: New file.
* include/bits/funcwrap.h: (_Ptrs::_M_obj): Const-qualify.
(_Storage::_M_ptr, _Storage::_M_ref): Remove.
(__polyfunc::__cast_to) Define.
(_Base_invoker::_S_ptrs, _Base_invoker::_S_nttp)
(_Base_invoker::_S_bind_ptrs, _Base_invoker::_S_bind_ref)
(_Base_invoker::_S_call_ptrs): Define.
(_Base_invoker::_S_call_storage): Foward to _S_call_ptrs.
(_Manager::_S_local, _Manager::_S_ptr): Adjust for _M_obj being
const qualified.
(__polyfunc::_Manager, __polyfunc::_Mo_base): Guard with
__glibcxx_move_only_function || __glibcxx_copyable_function.
(__polyfunc::__skip_first_arg, __polyfunc::__deduce_funcref)
(std::function_ref) [__glibcxx_function_ref]: Define.
* include/bits/utility.h (std::nontype_t, std::nontype)
(__is_nontype_v) [__glibcxx_function_ref]: Define.
* include/bits/version.def: Define function_ref.
* include/bits/version.h: Regenerate.
* include/std/functional: Define __cpp_lib_function_ref.
* src/c++23/std.cc.in (std::nontype_t, std::nontype)
(std::function_ref) [__cpp_lib_function_ref]: Export.
* testsuite/20_util/function_ref/assign.cc: New test.
* testsuite/20_util/function_ref/call.cc: New test.
* testsuite/20_util/function_ref/cons.cc: New test.
* testsuite/20_util/function_ref/cons_neg.cc: New test.
* testsuite/20_util/function_ref/conv.cc: New test.
* testsuite/20_util/function_ref/deduction.cc: New test.
* testsuite/20_util/function_ref/mutation.cc: New test.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-14 12:04:24 +02:00
|
|
|
const void* _M_obj;
|
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 <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-08 08:08:43 +02:00
|
|
|
void (*_M_func)();
|
2021-10-06 13:28:57 +01:00
|
|
|
};
|
|
|
|
|
|
libstdc++: Implement C++26 function_ref [PR119126]
This patch implements C++26 function_ref as specified in P0792R14,
with correction for constraints for constructor accepting nontype_t
parameter from LWG 4256.
As function_ref may store a pointer to the const object, __Ptrs::_M_obj is
changed to const void*, so again we do not cast away const from const
objects. To help with necessary casts, a __polyfunc::__cast_to helper is
added, that accepts reference to or target type direclty.
The _Invoker now defines additional call methods used by function_ref:
_S_ptrs() for invoking target passed by reference, and __S_nttp, _S_bind_ptr,
_S_bind_ref for handling constructors accepting nontype_t. The existing
_S_call_storage is changed to thin wrapper, that initialies _Ptrs, and forwards
to _S_call_ptrs.
This reduced the most uses of _Storage::_M_ptr and _Storage::_M_ref,
so this functions was removed, and _Manager uses were adjusted.
Finally we make function_ref available in freestanding mode, as
move_only_function and copyable_function are currently only available in hosted,
so we define _Manager and _Mo_base only if either __glibcxx_move_only_function
or __glibcxx_copyable_function is defined.
PR libstdc++/119126
libstdc++-v3/ChangeLog:
* doc/doxygen/stdheader.cc: Added funcref_impl.h file.
* include/Makefile.am: Added funcref_impl.h file.
* include/Makefile.in: Added funcref_impl.h file.
* include/bits/funcref_impl.h: New file.
* include/bits/funcwrap.h: (_Ptrs::_M_obj): Const-qualify.
(_Storage::_M_ptr, _Storage::_M_ref): Remove.
(__polyfunc::__cast_to) Define.
(_Base_invoker::_S_ptrs, _Base_invoker::_S_nttp)
(_Base_invoker::_S_bind_ptrs, _Base_invoker::_S_bind_ref)
(_Base_invoker::_S_call_ptrs): Define.
(_Base_invoker::_S_call_storage): Foward to _S_call_ptrs.
(_Manager::_S_local, _Manager::_S_ptr): Adjust for _M_obj being
const qualified.
(__polyfunc::_Manager, __polyfunc::_Mo_base): Guard with
__glibcxx_move_only_function || __glibcxx_copyable_function.
(__polyfunc::__skip_first_arg, __polyfunc::__deduce_funcref)
(std::function_ref) [__glibcxx_function_ref]: Define.
* include/bits/utility.h (std::nontype_t, std::nontype)
(__is_nontype_v) [__glibcxx_function_ref]: Define.
* include/bits/version.def: Define function_ref.
* include/bits/version.h: Regenerate.
* include/std/functional: Define __cpp_lib_function_ref.
* src/c++23/std.cc.in (std::nontype_t, std::nontype)
(std::function_ref) [__cpp_lib_function_ref]: Export.
* testsuite/20_util/function_ref/assign.cc: New test.
* testsuite/20_util/function_ref/call.cc: New test.
* testsuite/20_util/function_ref/cons.cc: New test.
* testsuite/20_util/function_ref/cons_neg.cc: New test.
* testsuite/20_util/function_ref/conv.cc: New test.
* testsuite/20_util/function_ref/deduction.cc: New test.
* testsuite/20_util/function_ref/mutation.cc: New test.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-14 12:04:24 +02:00
|
|
|
template<typename _Tp>
|
|
|
|
|
[[__gnu__::__always_inline__]]
|
|
|
|
|
constexpr auto*
|
|
|
|
|
__cast_to(_Ptrs __ptrs) noexcept
|
|
|
|
|
{
|
|
|
|
|
using _Td = remove_reference_t<_Tp>;
|
|
|
|
|
if constexpr (is_function_v<_Td>)
|
|
|
|
|
return reinterpret_cast<_Td*>(__ptrs._M_func);
|
|
|
|
|
else if constexpr (is_const_v<_Td>)
|
|
|
|
|
return static_cast<_Td*>(__ptrs._M_obj);
|
|
|
|
|
else
|
|
|
|
|
return static_cast<_Td*>(const_cast<void*>(__ptrs._M_obj));
|
|
|
|
|
}
|
|
|
|
|
|
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 <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-08 08:08:43 +02:00
|
|
|
struct _Storage
|
|
|
|
|
{
|
|
|
|
|
void* _M_addr() noexcept { return &_M_bytes[0]; }
|
|
|
|
|
void const* _M_addr() const noexcept { return &_M_bytes[0]; }
|
|
|
|
|
|
|
|
|
|
template<typename _Tp>
|
|
|
|
|
static consteval bool
|
|
|
|
|
_S_stored_locally() noexcept
|
|
|
|
|
{
|
|
|
|
|
return sizeof(_Tp) <= sizeof(_Storage)
|
|
|
|
|
&& alignof(_Tp) <= alignof(_Storage)
|
|
|
|
|
&& is_nothrow_move_constructible_v<_Tp>;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename _Tp, typename... _Args>
|
|
|
|
|
static consteval bool
|
|
|
|
|
_S_nothrow_init() noexcept
|
|
|
|
|
{
|
|
|
|
|
if constexpr (_S_stored_locally<_Tp>())
|
|
|
|
|
return is_nothrow_constructible_v<_Tp, _Args...>;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename _Tp, typename... _Args>
|
|
|
|
|
void
|
|
|
|
|
_M_init(_Args&&... __args) noexcept(_S_nothrow_init<_Tp, _Args...>())
|
|
|
|
|
{
|
|
|
|
|
if constexpr (is_function_v<remove_pointer_t<_Tp>>)
|
|
|
|
|
{
|
|
|
|
|
static_assert( sizeof...(__args) <= 1 );
|
|
|
|
|
// __args can have up to one element, returns nullptr if empty.
|
|
|
|
|
_Tp __func = (nullptr, ..., __args);
|
|
|
|
|
_M_ptrs._M_func = reinterpret_cast<void(*)()>(__func);
|
|
|
|
|
}
|
|
|
|
|
else if constexpr (!_S_stored_locally<_Tp>())
|
|
|
|
|
_M_ptrs._M_obj = new _Tp(std::forward<_Args>(__args)...);
|
|
|
|
|
else
|
|
|
|
|
::new (_M_addr()) _Tp(std::forward<_Args>(__args)...);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We want to have enough space to store a simple delegate type.
|
|
|
|
|
struct _Delegate { void (_Storage::*__pfm)(); _Storage* __obj; };
|
|
|
|
|
union {
|
|
|
|
|
_Ptrs _M_ptrs;
|
|
|
|
|
alignas(_Delegate) alignas(void(*)())
|
|
|
|
|
unsigned char _M_bytes[sizeof(_Delegate)];
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template<bool _Noex, typename _Ret, typename... _Args>
|
|
|
|
|
struct _Base_invoker
|
|
|
|
|
{
|
|
|
|
|
using _Signature = _Ret(*)(_Args...) noexcept(_Noex);
|
|
|
|
|
|
|
|
|
|
using __storage_func_t = _Ret(*)(const _Storage&, _Args...) noexcept(_Noex);
|
|
|
|
|
template<typename _Tp>
|
|
|
|
|
static consteval __storage_func_t
|
|
|
|
|
_S_storage()
|
|
|
|
|
{ return &_S_call_storage<_Adjust_target<_Tp>>; }
|
|
|
|
|
|
libstdc++: Implement C++26 function_ref [PR119126]
This patch implements C++26 function_ref as specified in P0792R14,
with correction for constraints for constructor accepting nontype_t
parameter from LWG 4256.
As function_ref may store a pointer to the const object, __Ptrs::_M_obj is
changed to const void*, so again we do not cast away const from const
objects. To help with necessary casts, a __polyfunc::__cast_to helper is
added, that accepts reference to or target type direclty.
The _Invoker now defines additional call methods used by function_ref:
_S_ptrs() for invoking target passed by reference, and __S_nttp, _S_bind_ptr,
_S_bind_ref for handling constructors accepting nontype_t. The existing
_S_call_storage is changed to thin wrapper, that initialies _Ptrs, and forwards
to _S_call_ptrs.
This reduced the most uses of _Storage::_M_ptr and _Storage::_M_ref,
so this functions was removed, and _Manager uses were adjusted.
Finally we make function_ref available in freestanding mode, as
move_only_function and copyable_function are currently only available in hosted,
so we define _Manager and _Mo_base only if either __glibcxx_move_only_function
or __glibcxx_copyable_function is defined.
PR libstdc++/119126
libstdc++-v3/ChangeLog:
* doc/doxygen/stdheader.cc: Added funcref_impl.h file.
* include/Makefile.am: Added funcref_impl.h file.
* include/Makefile.in: Added funcref_impl.h file.
* include/bits/funcref_impl.h: New file.
* include/bits/funcwrap.h: (_Ptrs::_M_obj): Const-qualify.
(_Storage::_M_ptr, _Storage::_M_ref): Remove.
(__polyfunc::__cast_to) Define.
(_Base_invoker::_S_ptrs, _Base_invoker::_S_nttp)
(_Base_invoker::_S_bind_ptrs, _Base_invoker::_S_bind_ref)
(_Base_invoker::_S_call_ptrs): Define.
(_Base_invoker::_S_call_storage): Foward to _S_call_ptrs.
(_Manager::_S_local, _Manager::_S_ptr): Adjust for _M_obj being
const qualified.
(__polyfunc::_Manager, __polyfunc::_Mo_base): Guard with
__glibcxx_move_only_function || __glibcxx_copyable_function.
(__polyfunc::__skip_first_arg, __polyfunc::__deduce_funcref)
(std::function_ref) [__glibcxx_function_ref]: Define.
* include/bits/utility.h (std::nontype_t, std::nontype)
(__is_nontype_v) [__glibcxx_function_ref]: Define.
* include/bits/version.def: Define function_ref.
* include/bits/version.h: Regenerate.
* include/std/functional: Define __cpp_lib_function_ref.
* src/c++23/std.cc.in (std::nontype_t, std::nontype)
(std::function_ref) [__cpp_lib_function_ref]: Export.
* testsuite/20_util/function_ref/assign.cc: New test.
* testsuite/20_util/function_ref/call.cc: New test.
* testsuite/20_util/function_ref/cons.cc: New test.
* testsuite/20_util/function_ref/cons_neg.cc: New test.
* testsuite/20_util/function_ref/conv.cc: New test.
* testsuite/20_util/function_ref/deduction.cc: New test.
* testsuite/20_util/function_ref/mutation.cc: New test.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-14 12:04:24 +02:00
|
|
|
using __ptrs_func_t = _Ret(*)(_Ptrs, _Args...) noexcept(_Noex);
|
|
|
|
|
template<typename _Tp>
|
|
|
|
|
static consteval __ptrs_func_t
|
|
|
|
|
_S_ptrs()
|
|
|
|
|
{ return &_S_call_ptrs<_Adjust_target<_Tp>>; }
|
|
|
|
|
|
|
|
|
|
#ifdef __glibcxx_function_ref // C++ >= 26
|
libstdc++: Make function_ref non-dangling for stateless wrappers
This patch makes the function_ref non-dangling for the stateless
wrappers:
* any functor for which operator() selected for arguments is static,
* standard functors, including pre-C++20 ones.
In other words, any function_ref fr, that is constructed from stateless
wrapper w, can be still called after the object w is destroyed, e.g.:
std::function_ref<bool(int, int)> fr(std::ranges::less{});
fr(1, 2); // OK, previously UB because fr referred to already destroyed
// temporary
As function_ref's operator() is not constexpr, we test the change by checking
if the above declaration can be made constexpr, as such variable cannot contain
dangling pointer values.
We adjust the function_ref generic constructor from any functor, to use more
specialized invoker:
* _S_static (newly added) if the called operator() overload is static,
after changes r16-5624-g0ea9d760fbf44c, this covers all post-c++20 functors;
* _S_nttp<_Fd{}> for pre-C++20 standard functors.
In both above cases the value of _M_ptrs is ignored and simply set to nullptr.
This follows same technique (checking _Fd::operator()(args...)), and support
the same set of types, as for one used for the transform views iterators in
r16-5625-g9ed821d107f7a1.
As after this change we provide well-defined behavior for the code, that
previous was undefined, this changes is pure quality-of-implementation.
As illustrated by the test cases, it has observable side effects, where
non-longer dangling constructs can be used to define constexpr function_ref.
However, the standard does not define when the constructors defined constexpr
are actually usable at compile time, and the already have precedent in form
of SSO string for validity such constructs being implementation specific.
libstdc++-v3/ChangeLog:
* include/bits/funcref_impl.h (function_ref::function_ref(_Fn&&)):
Use _S_static and _S_nttp invokers.
* include/bits/funcwrap.h (_Base_invoker::_S_static):
Define.
* include/bits/stl_function.h (std::__is_std_op_template)
(std::__is_std_op_wrapper) [__cplusplus > 201703L]:
Moved from std/ranges.
* include/std/ranges (__detail::__is_std_op_template)
(__detail::__is_std_op_wrapper): Moved to bits/stl_function.h.
* testsuite/20_util/function_ref/dangling.cc: New test.
* testsuite/20_util/function_ref/dangling_neg.cc: New test.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2026-02-02 10:19:51 +01:00
|
|
|
template<typename _Fn>
|
|
|
|
|
static _Ret
|
|
|
|
|
_S_static(_Ptrs, _Args... __args) noexcept(_Noex)
|
|
|
|
|
{ return _Fn::operator()(std::forward<_Args>(__args)...); }
|
|
|
|
|
|
libstdc++: Implement C++26 function_ref [PR119126]
This patch implements C++26 function_ref as specified in P0792R14,
with correction for constraints for constructor accepting nontype_t
parameter from LWG 4256.
As function_ref may store a pointer to the const object, __Ptrs::_M_obj is
changed to const void*, so again we do not cast away const from const
objects. To help with necessary casts, a __polyfunc::__cast_to helper is
added, that accepts reference to or target type direclty.
The _Invoker now defines additional call methods used by function_ref:
_S_ptrs() for invoking target passed by reference, and __S_nttp, _S_bind_ptr,
_S_bind_ref for handling constructors accepting nontype_t. The existing
_S_call_storage is changed to thin wrapper, that initialies _Ptrs, and forwards
to _S_call_ptrs.
This reduced the most uses of _Storage::_M_ptr and _Storage::_M_ref,
so this functions was removed, and _Manager uses were adjusted.
Finally we make function_ref available in freestanding mode, as
move_only_function and copyable_function are currently only available in hosted,
so we define _Manager and _Mo_base only if either __glibcxx_move_only_function
or __glibcxx_copyable_function is defined.
PR libstdc++/119126
libstdc++-v3/ChangeLog:
* doc/doxygen/stdheader.cc: Added funcref_impl.h file.
* include/Makefile.am: Added funcref_impl.h file.
* include/Makefile.in: Added funcref_impl.h file.
* include/bits/funcref_impl.h: New file.
* include/bits/funcwrap.h: (_Ptrs::_M_obj): Const-qualify.
(_Storage::_M_ptr, _Storage::_M_ref): Remove.
(__polyfunc::__cast_to) Define.
(_Base_invoker::_S_ptrs, _Base_invoker::_S_nttp)
(_Base_invoker::_S_bind_ptrs, _Base_invoker::_S_bind_ref)
(_Base_invoker::_S_call_ptrs): Define.
(_Base_invoker::_S_call_storage): Foward to _S_call_ptrs.
(_Manager::_S_local, _Manager::_S_ptr): Adjust for _M_obj being
const qualified.
(__polyfunc::_Manager, __polyfunc::_Mo_base): Guard with
__glibcxx_move_only_function || __glibcxx_copyable_function.
(__polyfunc::__skip_first_arg, __polyfunc::__deduce_funcref)
(std::function_ref) [__glibcxx_function_ref]: Define.
* include/bits/utility.h (std::nontype_t, std::nontype)
(__is_nontype_v) [__glibcxx_function_ref]: Define.
* include/bits/version.def: Define function_ref.
* include/bits/version.h: Regenerate.
* include/std/functional: Define __cpp_lib_function_ref.
* src/c++23/std.cc.in (std::nontype_t, std::nontype)
(std::function_ref) [__cpp_lib_function_ref]: Export.
* testsuite/20_util/function_ref/assign.cc: New test.
* testsuite/20_util/function_ref/call.cc: New test.
* testsuite/20_util/function_ref/cons.cc: New test.
* testsuite/20_util/function_ref/cons_neg.cc: New test.
* testsuite/20_util/function_ref/conv.cc: New test.
* testsuite/20_util/function_ref/deduction.cc: New test.
* testsuite/20_util/function_ref/mutation.cc: New test.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-14 12:04:24 +02:00
|
|
|
template<auto __fn>
|
|
|
|
|
static _Ret
|
|
|
|
|
_S_nttp(_Ptrs, _Args... __args) noexcept(_Noex)
|
|
|
|
|
{ return std::__invoke_r<_Ret>(__fn, std::forward<_Args>(__args)...); }
|
|
|
|
|
|
|
|
|
|
template<auto __fn, typename _Tp>
|
|
|
|
|
static _Ret
|
|
|
|
|
_S_bind_ptr(_Ptrs __ptrs, _Args... __args) noexcept(_Noex)
|
|
|
|
|
{
|
|
|
|
|
auto* __p = __polyfunc::__cast_to<_Tp>(__ptrs);
|
|
|
|
|
return std::__invoke_r<_Ret>(__fn, __p,
|
|
|
|
|
std::forward<_Args>(__args)...);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<auto __fn, typename _Ref>
|
|
|
|
|
static _Ret
|
|
|
|
|
_S_bind_ref(_Ptrs __ptrs, _Args... __args) noexcept(_Noex)
|
|
|
|
|
{
|
|
|
|
|
auto* __p = __polyfunc::__cast_to<_Ref>(__ptrs);
|
|
|
|
|
return std::__invoke_r<_Ret>(__fn, static_cast<_Ref>(*__p),
|
|
|
|
|
std::forward<_Args>(__args)...);
|
|
|
|
|
}
|
|
|
|
|
#endif // __glibcxx_function_ref
|
|
|
|
|
|
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 <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-08 08:08:43 +02:00
|
|
|
private:
|
|
|
|
|
template<typename _Tp, typename _Td = remove_cvref_t<_Tp>>
|
|
|
|
|
using _Adjust_target =
|
|
|
|
|
__conditional_t<is_pointer_v<_Td> || is_member_pointer_v<_Td>, _Td, _Tp>;
|
|
|
|
|
|
|
|
|
|
template<typename _Tp>
|
|
|
|
|
static _Ret
|
|
|
|
|
_S_call_storage(const _Storage& __ref, _Args... __args) noexcept(_Noex)
|
|
|
|
|
{
|
libstdc++: Implement C++26 function_ref [PR119126]
This patch implements C++26 function_ref as specified in P0792R14,
with correction for constraints for constructor accepting nontype_t
parameter from LWG 4256.
As function_ref may store a pointer to the const object, __Ptrs::_M_obj is
changed to const void*, so again we do not cast away const from const
objects. To help with necessary casts, a __polyfunc::__cast_to helper is
added, that accepts reference to or target type direclty.
The _Invoker now defines additional call methods used by function_ref:
_S_ptrs() for invoking target passed by reference, and __S_nttp, _S_bind_ptr,
_S_bind_ref for handling constructors accepting nontype_t. The existing
_S_call_storage is changed to thin wrapper, that initialies _Ptrs, and forwards
to _S_call_ptrs.
This reduced the most uses of _Storage::_M_ptr and _Storage::_M_ref,
so this functions was removed, and _Manager uses were adjusted.
Finally we make function_ref available in freestanding mode, as
move_only_function and copyable_function are currently only available in hosted,
so we define _Manager and _Mo_base only if either __glibcxx_move_only_function
or __glibcxx_copyable_function is defined.
PR libstdc++/119126
libstdc++-v3/ChangeLog:
* doc/doxygen/stdheader.cc: Added funcref_impl.h file.
* include/Makefile.am: Added funcref_impl.h file.
* include/Makefile.in: Added funcref_impl.h file.
* include/bits/funcref_impl.h: New file.
* include/bits/funcwrap.h: (_Ptrs::_M_obj): Const-qualify.
(_Storage::_M_ptr, _Storage::_M_ref): Remove.
(__polyfunc::__cast_to) Define.
(_Base_invoker::_S_ptrs, _Base_invoker::_S_nttp)
(_Base_invoker::_S_bind_ptrs, _Base_invoker::_S_bind_ref)
(_Base_invoker::_S_call_ptrs): Define.
(_Base_invoker::_S_call_storage): Foward to _S_call_ptrs.
(_Manager::_S_local, _Manager::_S_ptr): Adjust for _M_obj being
const qualified.
(__polyfunc::_Manager, __polyfunc::_Mo_base): Guard with
__glibcxx_move_only_function || __glibcxx_copyable_function.
(__polyfunc::__skip_first_arg, __polyfunc::__deduce_funcref)
(std::function_ref) [__glibcxx_function_ref]: Define.
* include/bits/utility.h (std::nontype_t, std::nontype)
(__is_nontype_v) [__glibcxx_function_ref]: Define.
* include/bits/version.def: Define function_ref.
* include/bits/version.h: Regenerate.
* include/std/functional: Define __cpp_lib_function_ref.
* src/c++23/std.cc.in (std::nontype_t, std::nontype)
(std::function_ref) [__cpp_lib_function_ref]: Export.
* testsuite/20_util/function_ref/assign.cc: New test.
* testsuite/20_util/function_ref/call.cc: New test.
* testsuite/20_util/function_ref/cons.cc: New test.
* testsuite/20_util/function_ref/cons_neg.cc: New test.
* testsuite/20_util/function_ref/conv.cc: New test.
* testsuite/20_util/function_ref/deduction.cc: New test.
* testsuite/20_util/function_ref/mutation.cc: New test.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-14 12:04:24 +02:00
|
|
|
_Ptrs __ptrs;
|
|
|
|
|
if constexpr (is_function_v<remove_pointer_t<_Tp>>)
|
|
|
|
|
__ptrs._M_func = __ref._M_ptrs._M_func;
|
|
|
|
|
else if constexpr (!_Storage::_S_stored_locally<remove_cvref_t<_Tp>>())
|
|
|
|
|
__ptrs._M_obj = __ref._M_ptrs._M_obj;
|
|
|
|
|
else
|
|
|
|
|
__ptrs._M_obj = __ref._M_addr();
|
|
|
|
|
return _S_call_ptrs<_Tp>(__ptrs, std::forward<_Args>(__args)...);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename _Tp>
|
|
|
|
|
static _Ret
|
|
|
|
|
_S_call_ptrs(_Ptrs __ptrs, _Args... __args) noexcept(_Noex)
|
|
|
|
|
{
|
|
|
|
|
if constexpr (is_function_v<remove_pointer_t<_Tp>>)
|
|
|
|
|
return std::__invoke_r<_Ret>(reinterpret_cast<_Tp>(__ptrs._M_func),
|
|
|
|
|
std::forward<_Args>(__args)...);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
auto* __p = __polyfunc::__cast_to<_Tp>(__ptrs);
|
|
|
|
|
return std::__invoke_r<_Ret>(static_cast<_Tp>(*__p),
|
|
|
|
|
std::forward<_Args>(__args)...);
|
|
|
|
|
}
|
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 <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-08 08:08:43 +02:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template<typename _Tp>
|
libstdc++: Pass small trivial types by value in polymorphic wrappers
This patch adjust the passing of parameters for the move_only_function,
copyable_function and function_ref. For types that are declared as being passed
by value in signature template argument, they are passed by value to the invoker,
when they are small (at most two pointers), trivially move constructible and
trivially destructible. The latter guarantees that passing them by value has not
user visible side effects.
In particular, this extends the set of types forwarded by value, that was
previously limited to scalars, to also include specializations of std::span and
std::string_view, and similar standard and program defined-types.
Checking the suitability of the parameter types requires the types to be complete.
As a consequence, the implementation imposes requirements on instantiation of
move_only_function and copyable_function. To avoid producing the errors from
the implementation details, a static assertion was added to partial
specializations of copyable_function, move_only_function and function_ref.
The static assertion uses existing __is_complete_or_unbounded, as arrays type
parameters are automatically decayed in function type.
Standard already specifies in [res.on.functions] p2.5 that instantiating these
partial specialization with incomplete types leads to undefined behavior.
libstdc++-v3/ChangeLog:
* include/bits/funcwrap.h (__polyfunc::__pass_by_rref): Define.
(__polyfunc::__param_t): Update to use __pass_by_rref.
* include/bits/cpyfunc_impl.h:: Assert that are parameters type
are complete.
* include/bits/funcref_impl.h: Likewise.
* include/bits/mofunc_impl.h: Likewise.
* testsuite/20_util/copyable_function/call.cc: New test.
* testsuite/20_util/function_ref/call.cc: New test.
* testsuite/20_util/move_only_function/call.cc: New test.
* testsuite/20_util/copyable_function/conv.cc: New test.
* testsuite/20_util/function_ref/conv.cc: New test.
* testsuite/20_util/move_only_function/conv.cc: New test.
* testsuite/20_util/copyable_function/incomplete_neg.cc: New test.
* testsuite/20_util/function_ref/incomplete_neg.cc: New test.
* testsuite/20_util/move_only_function/incomplete_neg.cc: New test.
Reviewed-by: Patrick Palka <ppalka@redhat.com>
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-28 11:16:22 +02:00
|
|
|
consteval bool
|
|
|
|
|
__pass_by_value()
|
|
|
|
|
{
|
|
|
|
|
// n.b. sizeof(Incomplete&) is ill-formed for incomplete types,
|
|
|
|
|
// so we check is_reference_v first.
|
|
|
|
|
if constexpr (is_reference_v<_Tp> || is_scalar_v<_Tp>)
|
|
|
|
|
return true;
|
|
|
|
|
else
|
|
|
|
|
// n.b. we already asserted that types are complete in wrappers,
|
|
|
|
|
// avoid triggering additional errors from this function.
|
|
|
|
|
if constexpr (std::__is_complete_or_unbounded(__type_identity<_Tp>()))
|
|
|
|
|
if constexpr (sizeof(_Tp) <= 2 * sizeof(void*))
|
|
|
|
|
return is_trivially_move_constructible_v<_Tp>
|
|
|
|
|
&& is_trivially_destructible_v<_Tp>;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<typename _Tp>
|
|
|
|
|
using __param_t = __conditional_t<__pass_by_value<_Tp>(), _Tp, _Tp&&>;
|
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 <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-08 08:08:43 +02:00
|
|
|
|
|
|
|
|
template<bool _Noex, typename _Ret, typename... _Args>
|
|
|
|
|
using _Invoker = _Base_invoker<_Noex, remove_cv_t<_Ret>, __param_t<_Args>...>;
|
|
|
|
|
|
|
|
|
|
template<typename _Func>
|
|
|
|
|
auto&
|
|
|
|
|
__invoker_of(_Func& __f) noexcept
|
|
|
|
|
{ return __f._M_invoke; }
|
|
|
|
|
|
|
|
|
|
template<typename _Func>
|
|
|
|
|
auto&
|
|
|
|
|
__base_of(_Func& __f) noexcept
|
|
|
|
|
{ return static_cast<__like_t<_Func&, typename _Func::_Base>>(__f); }
|
|
|
|
|
|
|
|
|
|
template<typename _Src, typename _Dst>
|
|
|
|
|
consteval bool
|
|
|
|
|
__is_invoker_convertible() noexcept
|
|
|
|
|
{
|
|
|
|
|
if constexpr (requires { typename _Src::_Signature; })
|
|
|
|
|
return is_convertible_v<typename _Src::_Signature,
|
|
|
|
|
typename _Dst::_Signature>;
|
|
|
|
|
else
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
libstdc++: Implement C++26 function_ref [PR119126]
This patch implements C++26 function_ref as specified in P0792R14,
with correction for constraints for constructor accepting nontype_t
parameter from LWG 4256.
As function_ref may store a pointer to the const object, __Ptrs::_M_obj is
changed to const void*, so again we do not cast away const from const
objects. To help with necessary casts, a __polyfunc::__cast_to helper is
added, that accepts reference to or target type direclty.
The _Invoker now defines additional call methods used by function_ref:
_S_ptrs() for invoking target passed by reference, and __S_nttp, _S_bind_ptr,
_S_bind_ref for handling constructors accepting nontype_t. The existing
_S_call_storage is changed to thin wrapper, that initialies _Ptrs, and forwards
to _S_call_ptrs.
This reduced the most uses of _Storage::_M_ptr and _Storage::_M_ref,
so this functions was removed, and _Manager uses were adjusted.
Finally we make function_ref available in freestanding mode, as
move_only_function and copyable_function are currently only available in hosted,
so we define _Manager and _Mo_base only if either __glibcxx_move_only_function
or __glibcxx_copyable_function is defined.
PR libstdc++/119126
libstdc++-v3/ChangeLog:
* doc/doxygen/stdheader.cc: Added funcref_impl.h file.
* include/Makefile.am: Added funcref_impl.h file.
* include/Makefile.in: Added funcref_impl.h file.
* include/bits/funcref_impl.h: New file.
* include/bits/funcwrap.h: (_Ptrs::_M_obj): Const-qualify.
(_Storage::_M_ptr, _Storage::_M_ref): Remove.
(__polyfunc::__cast_to) Define.
(_Base_invoker::_S_ptrs, _Base_invoker::_S_nttp)
(_Base_invoker::_S_bind_ptrs, _Base_invoker::_S_bind_ref)
(_Base_invoker::_S_call_ptrs): Define.
(_Base_invoker::_S_call_storage): Foward to _S_call_ptrs.
(_Manager::_S_local, _Manager::_S_ptr): Adjust for _M_obj being
const qualified.
(__polyfunc::_Manager, __polyfunc::_Mo_base): Guard with
__glibcxx_move_only_function || __glibcxx_copyable_function.
(__polyfunc::__skip_first_arg, __polyfunc::__deduce_funcref)
(std::function_ref) [__glibcxx_function_ref]: Define.
* include/bits/utility.h (std::nontype_t, std::nontype)
(__is_nontype_v) [__glibcxx_function_ref]: Define.
* include/bits/version.def: Define function_ref.
* include/bits/version.h: Regenerate.
* include/std/functional: Define __cpp_lib_function_ref.
* src/c++23/std.cc.in (std::nontype_t, std::nontype)
(std::function_ref) [__cpp_lib_function_ref]: Export.
* testsuite/20_util/function_ref/assign.cc: New test.
* testsuite/20_util/function_ref/call.cc: New test.
* testsuite/20_util/function_ref/cons.cc: New test.
* testsuite/20_util/function_ref/cons_neg.cc: New test.
* testsuite/20_util/function_ref/conv.cc: New test.
* testsuite/20_util/function_ref/deduction.cc: New test.
* testsuite/20_util/function_ref/mutation.cc: New test.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-14 12:04:24 +02:00
|
|
|
#if __glibcxx_move_only_function || __glibcxx_copyable_function
|
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 <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-08 08:08:43 +02:00
|
|
|
struct _Manager
|
|
|
|
|
{
|
|
|
|
|
enum class _Op
|
|
|
|
|
{
|
|
|
|
|
// saves address of entity in *__src to __target._M_ptrs,
|
|
|
|
|
_Address,
|
|
|
|
|
// moves entity stored in *__src to __target, __src becomes empty
|
|
|
|
|
_Move,
|
|
|
|
|
// copies entity stored in *__src to __target, supported only if
|
|
|
|
|
// _ProvideCopy is specified.
|
|
|
|
|
_Copy,
|
|
|
|
|
// destroys entity stored in __target, __src is ignoring
|
|
|
|
|
_Destroy,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// A function that performs operation __op on the __target and possibly __src.
|
libstdc++: Implement C++26 copyable_function [PR119125]
This patch implements C++26 copyable_function as specified in P2548R6.
It also implements LWG 4255 that adjust move_only_function so constructing
from empty copyable_function, produces empty functor. This falls from
existing checks, after specializing __is_polymorphic_function_v for
copyable_function specializations.
For compatible invoker signatures, the move_only_function may be constructed
from copyable_funciton without double indirection. To achieve that we derive
_Cpy_base from _Mo_base, and specialize __is_polymorphic_function_v for
copyable_function. Similary copyable_functions with compatible signatures
can be converted without double indirection.
As we starting to use _Op::_Copy operation from the _M_manage function,
invocations of that functions may now throw exceptions, so noexcept needs
to be removed from the signature of stored _M_manage pointers. This also
affects operations in _Mo_base, however we already wrap _M_manage invocations
in noexcept member functions (_M_move, _M_destroy, swap).
PR libstdc++/119125
libstdc++-v3/ChangeLog:
* doc/doxygen/stdheader.cc: Addded cpyfunc_impl.h header.
* include/Makefile.am: Add bits cpyfunc_impl.h.
* include/Makefile.in: Add bits cpyfunc_impl.h.
* include/bits/cpyfunc_impl.h: New file.
* include/bits/mofunc_impl.h: Mention LWG 4255.
* include/bits/move_only_function.h: Update header description
and change guard to also check __glibcxx_copyable_function.
(_Manager::_Func): Remove noexcept.
(std::__is_polymorphic_function_v<move_only_function<_Tp>>)
(__variant::_Never_valueless_alt<std::move_only_function<_Signature...>>)
(move_only_function) [__glibcxx_move_only_function]: Adjust guard.
(std::__is_polymorphic_function_v<copyable_function<_Tp>>)
(__variant::_Never_valueless_alt<std::copyable_function<_Signature...>>)
(__polyfunc::_Cpy_base, std::copyable_function)
[__glibcxx_copyable_function]: Define.
* include/bits/version.def: Define copyable_function.
* include/bits/version.h: Regenerate.
* include/std/functional: Define __cpp_lib_copyable_function.
* src/c++23/std.cc.in (copyable_function)
[__cpp_lib_copyable_function]: Export.
* testsuite/20_util/copyable_function/call.cc: New test based on
move_only_function tests.
* testsuite/20_util/copyable_function/cons.cc: New test based on
move_only_function tests.
* testsuite/20_util/copyable_function/conv.cc: New test based on
move_only_function tests.
* testsuite/20_util/copyable_function/copy.cc: New test.
* testsuite/20_util/copyable_function/move.cc: New test based on
move_only_function tests.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-12 10:01:22 +02:00
|
|
|
using _Func = void (*)(_Op __op, _Storage& __target, const _Storage* __src);
|
2021-10-06 13:28:57 +01:00
|
|
|
|
|
|
|
|
// The no-op manager function for objects with no target.
|
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 <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-08 08:08:43 +02:00
|
|
|
static void _S_empty(_Op, _Storage&, const _Storage*) noexcept { }
|
2021-10-06 13:28:57 +01:00
|
|
|
|
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 <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-08 08:08:43 +02:00
|
|
|
template<bool _ProvideCopy, typename _Tp>
|
|
|
|
|
consteval static auto
|
|
|
|
|
_S_select()
|
2021-10-06 13:28:57 +01:00
|
|
|
{
|
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 <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-08 08:08:43 +02:00
|
|
|
if constexpr (is_function_v<remove_pointer_t<_Tp>>)
|
|
|
|
|
return &_S_func;
|
|
|
|
|
else if constexpr (!_Storage::_S_stored_locally<_Tp>())
|
|
|
|
|
return &_S_ptr<_ProvideCopy, _Tp>;
|
|
|
|
|
else if constexpr (is_trivially_copyable_v<_Tp>)
|
|
|
|
|
return &_S_trivial;
|
2021-10-06 13:28:57 +01:00
|
|
|
else
|
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 <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-08 08:08:43 +02:00
|
|
|
return &_S_local<_ProvideCopy, _Tp>;
|
2021-10-06 13:28:57 +01:00
|
|
|
}
|
|
|
|
|
|
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 <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-08 08:08:43 +02:00
|
|
|
private:
|
|
|
|
|
static void
|
|
|
|
|
_S_func(_Op __op, _Storage& __target, const _Storage* __src) noexcept
|
|
|
|
|
{
|
|
|
|
|
switch (__op)
|
|
|
|
|
{
|
|
|
|
|
case _Op::_Address:
|
|
|
|
|
case _Op::_Move:
|
|
|
|
|
case _Op::_Copy:
|
|
|
|
|
__target._M_ptrs._M_func = __src->_M_ptrs._M_func;
|
|
|
|
|
return;
|
|
|
|
|
case _Op::_Destroy:
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_S_trivial(_Op __op, _Storage& __target, const _Storage* __src) noexcept
|
|
|
|
|
{
|
|
|
|
|
switch (__op)
|
|
|
|
|
{
|
|
|
|
|
case _Op::_Address:
|
libstdc++: Implement C++26 function_ref [PR119126]
This patch implements C++26 function_ref as specified in P0792R14,
with correction for constraints for constructor accepting nontype_t
parameter from LWG 4256.
As function_ref may store a pointer to the const object, __Ptrs::_M_obj is
changed to const void*, so again we do not cast away const from const
objects. To help with necessary casts, a __polyfunc::__cast_to helper is
added, that accepts reference to or target type direclty.
The _Invoker now defines additional call methods used by function_ref:
_S_ptrs() for invoking target passed by reference, and __S_nttp, _S_bind_ptr,
_S_bind_ref for handling constructors accepting nontype_t. The existing
_S_call_storage is changed to thin wrapper, that initialies _Ptrs, and forwards
to _S_call_ptrs.
This reduced the most uses of _Storage::_M_ptr and _Storage::_M_ref,
so this functions was removed, and _Manager uses were adjusted.
Finally we make function_ref available in freestanding mode, as
move_only_function and copyable_function are currently only available in hosted,
so we define _Manager and _Mo_base only if either __glibcxx_move_only_function
or __glibcxx_copyable_function is defined.
PR libstdc++/119126
libstdc++-v3/ChangeLog:
* doc/doxygen/stdheader.cc: Added funcref_impl.h file.
* include/Makefile.am: Added funcref_impl.h file.
* include/Makefile.in: Added funcref_impl.h file.
* include/bits/funcref_impl.h: New file.
* include/bits/funcwrap.h: (_Ptrs::_M_obj): Const-qualify.
(_Storage::_M_ptr, _Storage::_M_ref): Remove.
(__polyfunc::__cast_to) Define.
(_Base_invoker::_S_ptrs, _Base_invoker::_S_nttp)
(_Base_invoker::_S_bind_ptrs, _Base_invoker::_S_bind_ref)
(_Base_invoker::_S_call_ptrs): Define.
(_Base_invoker::_S_call_storage): Foward to _S_call_ptrs.
(_Manager::_S_local, _Manager::_S_ptr): Adjust for _M_obj being
const qualified.
(__polyfunc::_Manager, __polyfunc::_Mo_base): Guard with
__glibcxx_move_only_function || __glibcxx_copyable_function.
(__polyfunc::__skip_first_arg, __polyfunc::__deduce_funcref)
(std::function_ref) [__glibcxx_function_ref]: Define.
* include/bits/utility.h (std::nontype_t, std::nontype)
(__is_nontype_v) [__glibcxx_function_ref]: Define.
* include/bits/version.def: Define function_ref.
* include/bits/version.h: Regenerate.
* include/std/functional: Define __cpp_lib_function_ref.
* src/c++23/std.cc.in (std::nontype_t, std::nontype)
(std::function_ref) [__cpp_lib_function_ref]: Export.
* testsuite/20_util/function_ref/assign.cc: New test.
* testsuite/20_util/function_ref/call.cc: New test.
* testsuite/20_util/function_ref/cons.cc: New test.
* testsuite/20_util/function_ref/cons_neg.cc: New test.
* testsuite/20_util/function_ref/conv.cc: New test.
* testsuite/20_util/function_ref/deduction.cc: New test.
* testsuite/20_util/function_ref/mutation.cc: New test.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-14 12:04:24 +02:00
|
|
|
__target._M_ptrs._M_obj = __src->_M_addr();
|
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 <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-08 08:08:43 +02:00
|
|
|
return;
|
|
|
|
|
case _Op::_Move:
|
|
|
|
|
case _Op::_Copy:
|
|
|
|
|
// N.B. Creating _Storage starts lifetime of _M_bytes char array,
|
|
|
|
|
// that implicitly creates, amongst other, all possible trivially
|
|
|
|
|
// copyable objects, so we copy any object present in __src._M_bytes.
|
|
|
|
|
::new (&__target) _Storage(*__src);
|
|
|
|
|
return;
|
|
|
|
|
case _Op::_Destroy:
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<bool _Provide_copy, typename _Tp>
|
|
|
|
|
static void
|
|
|
|
|
_S_local(_Op __op, _Storage& __target, const _Storage* __src)
|
|
|
|
|
noexcept(!_Provide_copy)
|
|
|
|
|
{
|
|
|
|
|
switch (__op)
|
|
|
|
|
{
|
|
|
|
|
case _Op::_Address:
|
libstdc++: Implement C++26 function_ref [PR119126]
This patch implements C++26 function_ref as specified in P0792R14,
with correction for constraints for constructor accepting nontype_t
parameter from LWG 4256.
As function_ref may store a pointer to the const object, __Ptrs::_M_obj is
changed to const void*, so again we do not cast away const from const
objects. To help with necessary casts, a __polyfunc::__cast_to helper is
added, that accepts reference to or target type direclty.
The _Invoker now defines additional call methods used by function_ref:
_S_ptrs() for invoking target passed by reference, and __S_nttp, _S_bind_ptr,
_S_bind_ref for handling constructors accepting nontype_t. The existing
_S_call_storage is changed to thin wrapper, that initialies _Ptrs, and forwards
to _S_call_ptrs.
This reduced the most uses of _Storage::_M_ptr and _Storage::_M_ref,
so this functions was removed, and _Manager uses were adjusted.
Finally we make function_ref available in freestanding mode, as
move_only_function and copyable_function are currently only available in hosted,
so we define _Manager and _Mo_base only if either __glibcxx_move_only_function
or __glibcxx_copyable_function is defined.
PR libstdc++/119126
libstdc++-v3/ChangeLog:
* doc/doxygen/stdheader.cc: Added funcref_impl.h file.
* include/Makefile.am: Added funcref_impl.h file.
* include/Makefile.in: Added funcref_impl.h file.
* include/bits/funcref_impl.h: New file.
* include/bits/funcwrap.h: (_Ptrs::_M_obj): Const-qualify.
(_Storage::_M_ptr, _Storage::_M_ref): Remove.
(__polyfunc::__cast_to) Define.
(_Base_invoker::_S_ptrs, _Base_invoker::_S_nttp)
(_Base_invoker::_S_bind_ptrs, _Base_invoker::_S_bind_ref)
(_Base_invoker::_S_call_ptrs): Define.
(_Base_invoker::_S_call_storage): Foward to _S_call_ptrs.
(_Manager::_S_local, _Manager::_S_ptr): Adjust for _M_obj being
const qualified.
(__polyfunc::_Manager, __polyfunc::_Mo_base): Guard with
__glibcxx_move_only_function || __glibcxx_copyable_function.
(__polyfunc::__skip_first_arg, __polyfunc::__deduce_funcref)
(std::function_ref) [__glibcxx_function_ref]: Define.
* include/bits/utility.h (std::nontype_t, std::nontype)
(__is_nontype_v) [__glibcxx_function_ref]: Define.
* include/bits/version.def: Define function_ref.
* include/bits/version.h: Regenerate.
* include/std/functional: Define __cpp_lib_function_ref.
* src/c++23/std.cc.in (std::nontype_t, std::nontype)
(std::function_ref) [__cpp_lib_function_ref]: Export.
* testsuite/20_util/function_ref/assign.cc: New test.
* testsuite/20_util/function_ref/call.cc: New test.
* testsuite/20_util/function_ref/cons.cc: New test.
* testsuite/20_util/function_ref/cons_neg.cc: New test.
* testsuite/20_util/function_ref/conv.cc: New test.
* testsuite/20_util/function_ref/deduction.cc: New test.
* testsuite/20_util/function_ref/mutation.cc: New test.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-14 12:04:24 +02:00
|
|
|
__target._M_ptrs._M_obj = __src->_M_addr();
|
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 <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-08 08:08:43 +02:00
|
|
|
return;
|
|
|
|
|
case _Op::_Move:
|
|
|
|
|
{
|
libstdc++: Implement C++26 function_ref [PR119126]
This patch implements C++26 function_ref as specified in P0792R14,
with correction for constraints for constructor accepting nontype_t
parameter from LWG 4256.
As function_ref may store a pointer to the const object, __Ptrs::_M_obj is
changed to const void*, so again we do not cast away const from const
objects. To help with necessary casts, a __polyfunc::__cast_to helper is
added, that accepts reference to or target type direclty.
The _Invoker now defines additional call methods used by function_ref:
_S_ptrs() for invoking target passed by reference, and __S_nttp, _S_bind_ptr,
_S_bind_ref for handling constructors accepting nontype_t. The existing
_S_call_storage is changed to thin wrapper, that initialies _Ptrs, and forwards
to _S_call_ptrs.
This reduced the most uses of _Storage::_M_ptr and _Storage::_M_ref,
so this functions was removed, and _Manager uses were adjusted.
Finally we make function_ref available in freestanding mode, as
move_only_function and copyable_function are currently only available in hosted,
so we define _Manager and _Mo_base only if either __glibcxx_move_only_function
or __glibcxx_copyable_function is defined.
PR libstdc++/119126
libstdc++-v3/ChangeLog:
* doc/doxygen/stdheader.cc: Added funcref_impl.h file.
* include/Makefile.am: Added funcref_impl.h file.
* include/Makefile.in: Added funcref_impl.h file.
* include/bits/funcref_impl.h: New file.
* include/bits/funcwrap.h: (_Ptrs::_M_obj): Const-qualify.
(_Storage::_M_ptr, _Storage::_M_ref): Remove.
(__polyfunc::__cast_to) Define.
(_Base_invoker::_S_ptrs, _Base_invoker::_S_nttp)
(_Base_invoker::_S_bind_ptrs, _Base_invoker::_S_bind_ref)
(_Base_invoker::_S_call_ptrs): Define.
(_Base_invoker::_S_call_storage): Foward to _S_call_ptrs.
(_Manager::_S_local, _Manager::_S_ptr): Adjust for _M_obj being
const qualified.
(__polyfunc::_Manager, __polyfunc::_Mo_base): Guard with
__glibcxx_move_only_function || __glibcxx_copyable_function.
(__polyfunc::__skip_first_arg, __polyfunc::__deduce_funcref)
(std::function_ref) [__glibcxx_function_ref]: Define.
* include/bits/utility.h (std::nontype_t, std::nontype)
(__is_nontype_v) [__glibcxx_function_ref]: Define.
* include/bits/version.def: Define function_ref.
* include/bits/version.h: Regenerate.
* include/std/functional: Define __cpp_lib_function_ref.
* src/c++23/std.cc.in (std::nontype_t, std::nontype)
(std::function_ref) [__cpp_lib_function_ref]: Export.
* testsuite/20_util/function_ref/assign.cc: New test.
* testsuite/20_util/function_ref/call.cc: New test.
* testsuite/20_util/function_ref/cons.cc: New test.
* testsuite/20_util/function_ref/cons_neg.cc: New test.
* testsuite/20_util/function_ref/conv.cc: New test.
* testsuite/20_util/function_ref/deduction.cc: New test.
* testsuite/20_util/function_ref/mutation.cc: New test.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-14 12:04:24 +02:00
|
|
|
_Tp* __obj = static_cast<_Tp*>(const_cast<void*>(__src->_M_addr()));
|
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 <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-08 08:08:43 +02:00
|
|
|
::new(__target._M_addr()) _Tp(std::move(*__obj));
|
|
|
|
|
__obj->~_Tp();
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
case _Op::_Destroy:
|
libstdc++: Implement C++26 function_ref [PR119126]
This patch implements C++26 function_ref as specified in P0792R14,
with correction for constraints for constructor accepting nontype_t
parameter from LWG 4256.
As function_ref may store a pointer to the const object, __Ptrs::_M_obj is
changed to const void*, so again we do not cast away const from const
objects. To help with necessary casts, a __polyfunc::__cast_to helper is
added, that accepts reference to or target type direclty.
The _Invoker now defines additional call methods used by function_ref:
_S_ptrs() for invoking target passed by reference, and __S_nttp, _S_bind_ptr,
_S_bind_ref for handling constructors accepting nontype_t. The existing
_S_call_storage is changed to thin wrapper, that initialies _Ptrs, and forwards
to _S_call_ptrs.
This reduced the most uses of _Storage::_M_ptr and _Storage::_M_ref,
so this functions was removed, and _Manager uses were adjusted.
Finally we make function_ref available in freestanding mode, as
move_only_function and copyable_function are currently only available in hosted,
so we define _Manager and _Mo_base only if either __glibcxx_move_only_function
or __glibcxx_copyable_function is defined.
PR libstdc++/119126
libstdc++-v3/ChangeLog:
* doc/doxygen/stdheader.cc: Added funcref_impl.h file.
* include/Makefile.am: Added funcref_impl.h file.
* include/Makefile.in: Added funcref_impl.h file.
* include/bits/funcref_impl.h: New file.
* include/bits/funcwrap.h: (_Ptrs::_M_obj): Const-qualify.
(_Storage::_M_ptr, _Storage::_M_ref): Remove.
(__polyfunc::__cast_to) Define.
(_Base_invoker::_S_ptrs, _Base_invoker::_S_nttp)
(_Base_invoker::_S_bind_ptrs, _Base_invoker::_S_bind_ref)
(_Base_invoker::_S_call_ptrs): Define.
(_Base_invoker::_S_call_storage): Foward to _S_call_ptrs.
(_Manager::_S_local, _Manager::_S_ptr): Adjust for _M_obj being
const qualified.
(__polyfunc::_Manager, __polyfunc::_Mo_base): Guard with
__glibcxx_move_only_function || __glibcxx_copyable_function.
(__polyfunc::__skip_first_arg, __polyfunc::__deduce_funcref)
(std::function_ref) [__glibcxx_function_ref]: Define.
* include/bits/utility.h (std::nontype_t, std::nontype)
(__is_nontype_v) [__glibcxx_function_ref]: Define.
* include/bits/version.def: Define function_ref.
* include/bits/version.h: Regenerate.
* include/std/functional: Define __cpp_lib_function_ref.
* src/c++23/std.cc.in (std::nontype_t, std::nontype)
(std::function_ref) [__cpp_lib_function_ref]: Export.
* testsuite/20_util/function_ref/assign.cc: New test.
* testsuite/20_util/function_ref/call.cc: New test.
* testsuite/20_util/function_ref/cons.cc: New test.
* testsuite/20_util/function_ref/cons_neg.cc: New test.
* testsuite/20_util/function_ref/conv.cc: New test.
* testsuite/20_util/function_ref/deduction.cc: New test.
* testsuite/20_util/function_ref/mutation.cc: New test.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-14 12:04:24 +02:00
|
|
|
static_cast<_Tp*>(__target._M_addr())->~_Tp();
|
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 <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-08 08:08:43 +02:00
|
|
|
return;
|
|
|
|
|
case _Op::_Copy:
|
|
|
|
|
if constexpr (_Provide_copy)
|
libstdc++: Implement C++26 function_ref [PR119126]
This patch implements C++26 function_ref as specified in P0792R14,
with correction for constraints for constructor accepting nontype_t
parameter from LWG 4256.
As function_ref may store a pointer to the const object, __Ptrs::_M_obj is
changed to const void*, so again we do not cast away const from const
objects. To help with necessary casts, a __polyfunc::__cast_to helper is
added, that accepts reference to or target type direclty.
The _Invoker now defines additional call methods used by function_ref:
_S_ptrs() for invoking target passed by reference, and __S_nttp, _S_bind_ptr,
_S_bind_ref for handling constructors accepting nontype_t. The existing
_S_call_storage is changed to thin wrapper, that initialies _Ptrs, and forwards
to _S_call_ptrs.
This reduced the most uses of _Storage::_M_ptr and _Storage::_M_ref,
so this functions was removed, and _Manager uses were adjusted.
Finally we make function_ref available in freestanding mode, as
move_only_function and copyable_function are currently only available in hosted,
so we define _Manager and _Mo_base only if either __glibcxx_move_only_function
or __glibcxx_copyable_function is defined.
PR libstdc++/119126
libstdc++-v3/ChangeLog:
* doc/doxygen/stdheader.cc: Added funcref_impl.h file.
* include/Makefile.am: Added funcref_impl.h file.
* include/Makefile.in: Added funcref_impl.h file.
* include/bits/funcref_impl.h: New file.
* include/bits/funcwrap.h: (_Ptrs::_M_obj): Const-qualify.
(_Storage::_M_ptr, _Storage::_M_ref): Remove.
(__polyfunc::__cast_to) Define.
(_Base_invoker::_S_ptrs, _Base_invoker::_S_nttp)
(_Base_invoker::_S_bind_ptrs, _Base_invoker::_S_bind_ref)
(_Base_invoker::_S_call_ptrs): Define.
(_Base_invoker::_S_call_storage): Foward to _S_call_ptrs.
(_Manager::_S_local, _Manager::_S_ptr): Adjust for _M_obj being
const qualified.
(__polyfunc::_Manager, __polyfunc::_Mo_base): Guard with
__glibcxx_move_only_function || __glibcxx_copyable_function.
(__polyfunc::__skip_first_arg, __polyfunc::__deduce_funcref)
(std::function_ref) [__glibcxx_function_ref]: Define.
* include/bits/utility.h (std::nontype_t, std::nontype)
(__is_nontype_v) [__glibcxx_function_ref]: Define.
* include/bits/version.def: Define function_ref.
* include/bits/version.h: Regenerate.
* include/std/functional: Define __cpp_lib_function_ref.
* src/c++23/std.cc.in (std::nontype_t, std::nontype)
(std::function_ref) [__cpp_lib_function_ref]: Export.
* testsuite/20_util/function_ref/assign.cc: New test.
* testsuite/20_util/function_ref/call.cc: New test.
* testsuite/20_util/function_ref/cons.cc: New test.
* testsuite/20_util/function_ref/cons_neg.cc: New test.
* testsuite/20_util/function_ref/conv.cc: New test.
* testsuite/20_util/function_ref/deduction.cc: New test.
* testsuite/20_util/function_ref/mutation.cc: New test.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-14 12:04:24 +02:00
|
|
|
{
|
|
|
|
|
auto* __obj = static_cast<const _Tp*>(__src->_M_addr());
|
|
|
|
|
::new (__target._M_addr()) _Tp(*__obj);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
__builtin_unreachable();
|
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 <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-08 08:08:43 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template<bool _Provide_copy, typename _Tp>
|
|
|
|
|
static void
|
|
|
|
|
_S_ptr(_Op __op, _Storage& __target, const _Storage* __src)
|
|
|
|
|
noexcept(!_Provide_copy)
|
|
|
|
|
{
|
|
|
|
|
switch (__op)
|
|
|
|
|
{
|
|
|
|
|
case _Op::_Address:
|
|
|
|
|
case _Op::_Move:
|
|
|
|
|
__target._M_ptrs._M_obj = __src->_M_ptrs._M_obj;
|
|
|
|
|
return;
|
|
|
|
|
case _Op::_Destroy:
|
libstdc++: Implement C++26 function_ref [PR119126]
This patch implements C++26 function_ref as specified in P0792R14,
with correction for constraints for constructor accepting nontype_t
parameter from LWG 4256.
As function_ref may store a pointer to the const object, __Ptrs::_M_obj is
changed to const void*, so again we do not cast away const from const
objects. To help with necessary casts, a __polyfunc::__cast_to helper is
added, that accepts reference to or target type direclty.
The _Invoker now defines additional call methods used by function_ref:
_S_ptrs() for invoking target passed by reference, and __S_nttp, _S_bind_ptr,
_S_bind_ref for handling constructors accepting nontype_t. The existing
_S_call_storage is changed to thin wrapper, that initialies _Ptrs, and forwards
to _S_call_ptrs.
This reduced the most uses of _Storage::_M_ptr and _Storage::_M_ref,
so this functions was removed, and _Manager uses were adjusted.
Finally we make function_ref available in freestanding mode, as
move_only_function and copyable_function are currently only available in hosted,
so we define _Manager and _Mo_base only if either __glibcxx_move_only_function
or __glibcxx_copyable_function is defined.
PR libstdc++/119126
libstdc++-v3/ChangeLog:
* doc/doxygen/stdheader.cc: Added funcref_impl.h file.
* include/Makefile.am: Added funcref_impl.h file.
* include/Makefile.in: Added funcref_impl.h file.
* include/bits/funcref_impl.h: New file.
* include/bits/funcwrap.h: (_Ptrs::_M_obj): Const-qualify.
(_Storage::_M_ptr, _Storage::_M_ref): Remove.
(__polyfunc::__cast_to) Define.
(_Base_invoker::_S_ptrs, _Base_invoker::_S_nttp)
(_Base_invoker::_S_bind_ptrs, _Base_invoker::_S_bind_ref)
(_Base_invoker::_S_call_ptrs): Define.
(_Base_invoker::_S_call_storage): Foward to _S_call_ptrs.
(_Manager::_S_local, _Manager::_S_ptr): Adjust for _M_obj being
const qualified.
(__polyfunc::_Manager, __polyfunc::_Mo_base): Guard with
__glibcxx_move_only_function || __glibcxx_copyable_function.
(__polyfunc::__skip_first_arg, __polyfunc::__deduce_funcref)
(std::function_ref) [__glibcxx_function_ref]: Define.
* include/bits/utility.h (std::nontype_t, std::nontype)
(__is_nontype_v) [__glibcxx_function_ref]: Define.
* include/bits/version.def: Define function_ref.
* include/bits/version.h: Regenerate.
* include/std/functional: Define __cpp_lib_function_ref.
* src/c++23/std.cc.in (std::nontype_t, std::nontype)
(std::function_ref) [__cpp_lib_function_ref]: Export.
* testsuite/20_util/function_ref/assign.cc: New test.
* testsuite/20_util/function_ref/call.cc: New test.
* testsuite/20_util/function_ref/cons.cc: New test.
* testsuite/20_util/function_ref/cons_neg.cc: New test.
* testsuite/20_util/function_ref/conv.cc: New test.
* testsuite/20_util/function_ref/deduction.cc: New test.
* testsuite/20_util/function_ref/mutation.cc: New test.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-14 12:04:24 +02:00
|
|
|
delete static_cast<const _Tp*>(__target._M_ptrs._M_obj);
|
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 <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-08 08:08:43 +02:00
|
|
|
return;
|
|
|
|
|
case _Op::_Copy:
|
|
|
|
|
if constexpr (_Provide_copy)
|
libstdc++: Implement C++26 function_ref [PR119126]
This patch implements C++26 function_ref as specified in P0792R14,
with correction for constraints for constructor accepting nontype_t
parameter from LWG 4256.
As function_ref may store a pointer to the const object, __Ptrs::_M_obj is
changed to const void*, so again we do not cast away const from const
objects. To help with necessary casts, a __polyfunc::__cast_to helper is
added, that accepts reference to or target type direclty.
The _Invoker now defines additional call methods used by function_ref:
_S_ptrs() for invoking target passed by reference, and __S_nttp, _S_bind_ptr,
_S_bind_ref for handling constructors accepting nontype_t. The existing
_S_call_storage is changed to thin wrapper, that initialies _Ptrs, and forwards
to _S_call_ptrs.
This reduced the most uses of _Storage::_M_ptr and _Storage::_M_ref,
so this functions was removed, and _Manager uses were adjusted.
Finally we make function_ref available in freestanding mode, as
move_only_function and copyable_function are currently only available in hosted,
so we define _Manager and _Mo_base only if either __glibcxx_move_only_function
or __glibcxx_copyable_function is defined.
PR libstdc++/119126
libstdc++-v3/ChangeLog:
* doc/doxygen/stdheader.cc: Added funcref_impl.h file.
* include/Makefile.am: Added funcref_impl.h file.
* include/Makefile.in: Added funcref_impl.h file.
* include/bits/funcref_impl.h: New file.
* include/bits/funcwrap.h: (_Ptrs::_M_obj): Const-qualify.
(_Storage::_M_ptr, _Storage::_M_ref): Remove.
(__polyfunc::__cast_to) Define.
(_Base_invoker::_S_ptrs, _Base_invoker::_S_nttp)
(_Base_invoker::_S_bind_ptrs, _Base_invoker::_S_bind_ref)
(_Base_invoker::_S_call_ptrs): Define.
(_Base_invoker::_S_call_storage): Foward to _S_call_ptrs.
(_Manager::_S_local, _Manager::_S_ptr): Adjust for _M_obj being
const qualified.
(__polyfunc::_Manager, __polyfunc::_Mo_base): Guard with
__glibcxx_move_only_function || __glibcxx_copyable_function.
(__polyfunc::__skip_first_arg, __polyfunc::__deduce_funcref)
(std::function_ref) [__glibcxx_function_ref]: Define.
* include/bits/utility.h (std::nontype_t, std::nontype)
(__is_nontype_v) [__glibcxx_function_ref]: Define.
* include/bits/version.def: Define function_ref.
* include/bits/version.h: Regenerate.
* include/std/functional: Define __cpp_lib_function_ref.
* src/c++23/std.cc.in (std::nontype_t, std::nontype)
(std::function_ref) [__cpp_lib_function_ref]: Export.
* testsuite/20_util/function_ref/assign.cc: New test.
* testsuite/20_util/function_ref/call.cc: New test.
* testsuite/20_util/function_ref/cons.cc: New test.
* testsuite/20_util/function_ref/cons_neg.cc: New test.
* testsuite/20_util/function_ref/conv.cc: New test.
* testsuite/20_util/function_ref/deduction.cc: New test.
* testsuite/20_util/function_ref/mutation.cc: New test.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-14 12:04:24 +02:00
|
|
|
{
|
|
|
|
|
auto* __obj = static_cast<const _Tp*>(__src->_M_ptrs._M_obj);
|
|
|
|
|
__target._M_ptrs._M_obj = new _Tp(*__obj);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
__builtin_unreachable();
|
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 <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-08 08:08:43 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class _Mo_base
|
|
|
|
|
{
|
|
|
|
|
protected:
|
|
|
|
|
_Mo_base() noexcept
|
|
|
|
|
: _M_manage(_Manager::_S_empty)
|
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
_Mo_base(_Mo_base&& __x) noexcept
|
|
|
|
|
{ _M_move(__x); }
|
|
|
|
|
|
|
|
|
|
template<typename _Tp, typename... _Args>
|
|
|
|
|
static consteval bool
|
|
|
|
|
_S_nothrow_init() noexcept
|
|
|
|
|
{ return _Storage::_S_nothrow_init<_Tp, _Args...>(); }
|
|
|
|
|
|
|
|
|
|
template<typename _Tp, typename... _Args>
|
|
|
|
|
void
|
|
|
|
|
_M_init(_Args&&... __args)
|
|
|
|
|
noexcept(_S_nothrow_init<_Tp, _Args...>())
|
|
|
|
|
{
|
|
|
|
|
_M_storage._M_init<_Tp>(std::forward<_Args>(__args)...);
|
|
|
|
|
_M_manage = _Manager::_S_select<false, _Tp>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
_M_move(_Mo_base& __x) noexcept
|
|
|
|
|
{
|
|
|
|
|
using _Op = _Manager::_Op;
|
|
|
|
|
_M_manage = std::__exchange(__x._M_manage, _Manager::_S_empty);
|
|
|
|
|
_M_manage(_Op::_Move, _M_storage, &__x._M_storage);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_Mo_base&
|
|
|
|
|
operator=(_Mo_base&& __x) noexcept
|
|
|
|
|
{
|
|
|
|
|
_M_destroy();
|
|
|
|
|
_M_move(__x);
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
_M_reset() noexcept
|
|
|
|
|
{
|
|
|
|
|
_M_destroy();
|
|
|
|
|
_M_manage = _Manager::_S_empty;
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-19 16:44:49 +02:00
|
|
|
void _M_destroy() noexcept
|
|
|
|
|
{ _M_manage(_Manager::_Op::_Destroy, _M_storage, nullptr); }
|
|
|
|
|
|
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 <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-08 08:08:43 +02:00
|
|
|
~_Mo_base()
|
|
|
|
|
{ _M_destroy(); }
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
swap(_Mo_base& __x) noexcept
|
|
|
|
|
{
|
|
|
|
|
using _Op = _Manager::_Op;
|
|
|
|
|
// Order of operations here is more efficient if __x is empty.
|
|
|
|
|
_Storage __s;
|
|
|
|
|
__x._M_manage(_Op::_Move, __s, &__x._M_storage);
|
|
|
|
|
_M_manage(_Op::_Move, __x._M_storage, &_M_storage);
|
|
|
|
|
__x._M_manage(_Op::_Move, _M_storage, &__s);
|
|
|
|
|
std::swap(_M_manage, __x._M_manage);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_Manager::_Func _M_manage;
|
2025-08-19 16:44:49 +02:00
|
|
|
_Storage _M_storage;
|
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 <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-08 08:08:43 +02:00
|
|
|
};
|
libstdc++: Implement C++26 function_ref [PR119126]
This patch implements C++26 function_ref as specified in P0792R14,
with correction for constraints for constructor accepting nontype_t
parameter from LWG 4256.
As function_ref may store a pointer to the const object, __Ptrs::_M_obj is
changed to const void*, so again we do not cast away const from const
objects. To help with necessary casts, a __polyfunc::__cast_to helper is
added, that accepts reference to or target type direclty.
The _Invoker now defines additional call methods used by function_ref:
_S_ptrs() for invoking target passed by reference, and __S_nttp, _S_bind_ptr,
_S_bind_ref for handling constructors accepting nontype_t. The existing
_S_call_storage is changed to thin wrapper, that initialies _Ptrs, and forwards
to _S_call_ptrs.
This reduced the most uses of _Storage::_M_ptr and _Storage::_M_ref,
so this functions was removed, and _Manager uses were adjusted.
Finally we make function_ref available in freestanding mode, as
move_only_function and copyable_function are currently only available in hosted,
so we define _Manager and _Mo_base only if either __glibcxx_move_only_function
or __glibcxx_copyable_function is defined.
PR libstdc++/119126
libstdc++-v3/ChangeLog:
* doc/doxygen/stdheader.cc: Added funcref_impl.h file.
* include/Makefile.am: Added funcref_impl.h file.
* include/Makefile.in: Added funcref_impl.h file.
* include/bits/funcref_impl.h: New file.
* include/bits/funcwrap.h: (_Ptrs::_M_obj): Const-qualify.
(_Storage::_M_ptr, _Storage::_M_ref): Remove.
(__polyfunc::__cast_to) Define.
(_Base_invoker::_S_ptrs, _Base_invoker::_S_nttp)
(_Base_invoker::_S_bind_ptrs, _Base_invoker::_S_bind_ref)
(_Base_invoker::_S_call_ptrs): Define.
(_Base_invoker::_S_call_storage): Foward to _S_call_ptrs.
(_Manager::_S_local, _Manager::_S_ptr): Adjust for _M_obj being
const qualified.
(__polyfunc::_Manager, __polyfunc::_Mo_base): Guard with
__glibcxx_move_only_function || __glibcxx_copyable_function.
(__polyfunc::__skip_first_arg, __polyfunc::__deduce_funcref)
(std::function_ref) [__glibcxx_function_ref]: Define.
* include/bits/utility.h (std::nontype_t, std::nontype)
(__is_nontype_v) [__glibcxx_function_ref]: Define.
* include/bits/version.def: Define function_ref.
* include/bits/version.h: Regenerate.
* include/std/functional: Define __cpp_lib_function_ref.
* src/c++23/std.cc.in (std::nontype_t, std::nontype)
(std::function_ref) [__cpp_lib_function_ref]: Export.
* testsuite/20_util/function_ref/assign.cc: New test.
* testsuite/20_util/function_ref/call.cc: New test.
* testsuite/20_util/function_ref/cons.cc: New test.
* testsuite/20_util/function_ref/cons_neg.cc: New test.
* testsuite/20_util/function_ref/conv.cc: New test.
* testsuite/20_util/function_ref/deduction.cc: New test.
* testsuite/20_util/function_ref/mutation.cc: New test.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-14 12:04:24 +02:00
|
|
|
#endif // __glibcxx_copyable_function || __glibcxx_copyable_function
|
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 <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-08 08:08:43 +02:00
|
|
|
} // namespace __polyfunc
|
|
|
|
|
/// @endcond
|
2021-10-06 13:28:57 +01:00
|
|
|
|
libstdc++: Implement C++26 copyable_function [PR119125]
This patch implements C++26 copyable_function as specified in P2548R6.
It also implements LWG 4255 that adjust move_only_function so constructing
from empty copyable_function, produces empty functor. This falls from
existing checks, after specializing __is_polymorphic_function_v for
copyable_function specializations.
For compatible invoker signatures, the move_only_function may be constructed
from copyable_funciton without double indirection. To achieve that we derive
_Cpy_base from _Mo_base, and specialize __is_polymorphic_function_v for
copyable_function. Similary copyable_functions with compatible signatures
can be converted without double indirection.
As we starting to use _Op::_Copy operation from the _M_manage function,
invocations of that functions may now throw exceptions, so noexcept needs
to be removed from the signature of stored _M_manage pointers. This also
affects operations in _Mo_base, however we already wrap _M_manage invocations
in noexcept member functions (_M_move, _M_destroy, swap).
PR libstdc++/119125
libstdc++-v3/ChangeLog:
* doc/doxygen/stdheader.cc: Addded cpyfunc_impl.h header.
* include/Makefile.am: Add bits cpyfunc_impl.h.
* include/Makefile.in: Add bits cpyfunc_impl.h.
* include/bits/cpyfunc_impl.h: New file.
* include/bits/mofunc_impl.h: Mention LWG 4255.
* include/bits/move_only_function.h: Update header description
and change guard to also check __glibcxx_copyable_function.
(_Manager::_Func): Remove noexcept.
(std::__is_polymorphic_function_v<move_only_function<_Tp>>)
(__variant::_Never_valueless_alt<std::move_only_function<_Signature...>>)
(move_only_function) [__glibcxx_move_only_function]: Adjust guard.
(std::__is_polymorphic_function_v<copyable_function<_Tp>>)
(__variant::_Never_valueless_alt<std::copyable_function<_Signature...>>)
(__polyfunc::_Cpy_base, std::copyable_function)
[__glibcxx_copyable_function]: Define.
* include/bits/version.def: Define copyable_function.
* include/bits/version.h: Regenerate.
* include/std/functional: Define __cpp_lib_copyable_function.
* src/c++23/std.cc.in (copyable_function)
[__cpp_lib_copyable_function]: Export.
* testsuite/20_util/copyable_function/call.cc: New test based on
move_only_function tests.
* testsuite/20_util/copyable_function/cons.cc: New test based on
move_only_function tests.
* testsuite/20_util/copyable_function/conv.cc: New test based on
move_only_function tests.
* testsuite/20_util/copyable_function/copy.cc: New test.
* testsuite/20_util/copyable_function/move.cc: New test based on
move_only_function tests.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-12 10:01:22 +02:00
|
|
|
#ifdef __glibcxx_move_only_function // C++ >= 23 && HOSTED
|
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 <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-08 08:08:43 +02:00
|
|
|
template<typename... _Signature>
|
|
|
|
|
class move_only_function; // not defined
|
|
|
|
|
|
|
|
|
|
/// @cond undocumented
|
2021-10-06 13:28:57 +01:00
|
|
|
template<typename _Tp>
|
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 <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-08 08:08:43 +02:00
|
|
|
constexpr bool __is_polymorphic_function_v<move_only_function<_Tp>> = true;
|
2021-10-06 13:28:57 +01:00
|
|
|
|
2022-06-23 18:42:55 +01:00
|
|
|
namespace __detail::__variant
|
|
|
|
|
{
|
|
|
|
|
template<typename> struct _Never_valueless_alt; // see <variant>
|
|
|
|
|
|
|
|
|
|
// Provide the strong exception-safety guarantee when emplacing a
|
|
|
|
|
// move_only_function into a variant.
|
|
|
|
|
template<typename... _Signature>
|
|
|
|
|
struct _Never_valueless_alt<std::move_only_function<_Signature...>>
|
|
|
|
|
: true_type
|
|
|
|
|
{ };
|
|
|
|
|
} // namespace __detail::__variant
|
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 <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-08 08:08:43 +02:00
|
|
|
/// @endcond
|
libstdc++: Implement C++26 copyable_function [PR119125]
This patch implements C++26 copyable_function as specified in P2548R6.
It also implements LWG 4255 that adjust move_only_function so constructing
from empty copyable_function, produces empty functor. This falls from
existing checks, after specializing __is_polymorphic_function_v for
copyable_function specializations.
For compatible invoker signatures, the move_only_function may be constructed
from copyable_funciton without double indirection. To achieve that we derive
_Cpy_base from _Mo_base, and specialize __is_polymorphic_function_v for
copyable_function. Similary copyable_functions with compatible signatures
can be converted without double indirection.
As we starting to use _Op::_Copy operation from the _M_manage function,
invocations of that functions may now throw exceptions, so noexcept needs
to be removed from the signature of stored _M_manage pointers. This also
affects operations in _Mo_base, however we already wrap _M_manage invocations
in noexcept member functions (_M_move, _M_destroy, swap).
PR libstdc++/119125
libstdc++-v3/ChangeLog:
* doc/doxygen/stdheader.cc: Addded cpyfunc_impl.h header.
* include/Makefile.am: Add bits cpyfunc_impl.h.
* include/Makefile.in: Add bits cpyfunc_impl.h.
* include/bits/cpyfunc_impl.h: New file.
* include/bits/mofunc_impl.h: Mention LWG 4255.
* include/bits/move_only_function.h: Update header description
and change guard to also check __glibcxx_copyable_function.
(_Manager::_Func): Remove noexcept.
(std::__is_polymorphic_function_v<move_only_function<_Tp>>)
(__variant::_Never_valueless_alt<std::move_only_function<_Signature...>>)
(move_only_function) [__glibcxx_move_only_function]: Adjust guard.
(std::__is_polymorphic_function_v<copyable_function<_Tp>>)
(__variant::_Never_valueless_alt<std::copyable_function<_Signature...>>)
(__polyfunc::_Cpy_base, std::copyable_function)
[__glibcxx_copyable_function]: Define.
* include/bits/version.def: Define copyable_function.
* include/bits/version.h: Regenerate.
* include/std/functional: Define __cpp_lib_copyable_function.
* src/c++23/std.cc.in (copyable_function)
[__cpp_lib_copyable_function]: Export.
* testsuite/20_util/copyable_function/call.cc: New test based on
move_only_function tests.
* testsuite/20_util/copyable_function/cons.cc: New test based on
move_only_function tests.
* testsuite/20_util/copyable_function/conv.cc: New test based on
move_only_function tests.
* testsuite/20_util/copyable_function/copy.cc: New test.
* testsuite/20_util/copyable_function/move.cc: New test based on
move_only_function tests.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-12 10:01:22 +02:00
|
|
|
#endif // __glibcxx_move_only_function
|
|
|
|
|
|
|
|
|
|
#ifdef __glibcxx_copyable_function // C++ >= 26 && HOSTED
|
|
|
|
|
/// @cond undocumented
|
|
|
|
|
namespace __polyfunc
|
|
|
|
|
{
|
|
|
|
|
class _Cpy_base : public _Mo_base
|
|
|
|
|
{
|
|
|
|
|
protected:
|
|
|
|
|
_Cpy_base() = default;
|
|
|
|
|
|
|
|
|
|
template<typename _Tp, typename... _Args>
|
|
|
|
|
void
|
|
|
|
|
_M_init(_Args&&... __args)
|
|
|
|
|
noexcept(_S_nothrow_init<_Tp, _Args...>())
|
|
|
|
|
{
|
|
|
|
|
_M_storage._M_init<_Tp>(std::forward<_Args>(__args)...);
|
|
|
|
|
_M_manage = _Manager::_S_select<true, _Tp>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
_M_copy(_Cpy_base const& __x)
|
|
|
|
|
{
|
|
|
|
|
using _Op = _Manager::_Op;
|
|
|
|
|
__x._M_manage(_Op::_Copy, _M_storage, &__x._M_storage);
|
|
|
|
|
_M_manage = __x._M_manage;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_Cpy_base(_Cpy_base&&) = default;
|
|
|
|
|
|
|
|
|
|
_Cpy_base(_Cpy_base const& __x)
|
2026-01-23 11:09:08 +01:00
|
|
|
: _Mo_base()
|
libstdc++: Implement C++26 copyable_function [PR119125]
This patch implements C++26 copyable_function as specified in P2548R6.
It also implements LWG 4255 that adjust move_only_function so constructing
from empty copyable_function, produces empty functor. This falls from
existing checks, after specializing __is_polymorphic_function_v for
copyable_function specializations.
For compatible invoker signatures, the move_only_function may be constructed
from copyable_funciton without double indirection. To achieve that we derive
_Cpy_base from _Mo_base, and specialize __is_polymorphic_function_v for
copyable_function. Similary copyable_functions with compatible signatures
can be converted without double indirection.
As we starting to use _Op::_Copy operation from the _M_manage function,
invocations of that functions may now throw exceptions, so noexcept needs
to be removed from the signature of stored _M_manage pointers. This also
affects operations in _Mo_base, however we already wrap _M_manage invocations
in noexcept member functions (_M_move, _M_destroy, swap).
PR libstdc++/119125
libstdc++-v3/ChangeLog:
* doc/doxygen/stdheader.cc: Addded cpyfunc_impl.h header.
* include/Makefile.am: Add bits cpyfunc_impl.h.
* include/Makefile.in: Add bits cpyfunc_impl.h.
* include/bits/cpyfunc_impl.h: New file.
* include/bits/mofunc_impl.h: Mention LWG 4255.
* include/bits/move_only_function.h: Update header description
and change guard to also check __glibcxx_copyable_function.
(_Manager::_Func): Remove noexcept.
(std::__is_polymorphic_function_v<move_only_function<_Tp>>)
(__variant::_Never_valueless_alt<std::move_only_function<_Signature...>>)
(move_only_function) [__glibcxx_move_only_function]: Adjust guard.
(std::__is_polymorphic_function_v<copyable_function<_Tp>>)
(__variant::_Never_valueless_alt<std::copyable_function<_Signature...>>)
(__polyfunc::_Cpy_base, std::copyable_function)
[__glibcxx_copyable_function]: Define.
* include/bits/version.def: Define copyable_function.
* include/bits/version.h: Regenerate.
* include/std/functional: Define __cpp_lib_copyable_function.
* src/c++23/std.cc.in (copyable_function)
[__cpp_lib_copyable_function]: Export.
* testsuite/20_util/copyable_function/call.cc: New test based on
move_only_function tests.
* testsuite/20_util/copyable_function/cons.cc: New test based on
move_only_function tests.
* testsuite/20_util/copyable_function/conv.cc: New test based on
move_only_function tests.
* testsuite/20_util/copyable_function/copy.cc: New test.
* testsuite/20_util/copyable_function/move.cc: New test based on
move_only_function tests.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-12 10:01:22 +02:00
|
|
|
{ _M_copy(__x); }
|
|
|
|
|
|
|
|
|
|
_Cpy_base&
|
|
|
|
|
operator=(_Cpy_base&&) = default;
|
|
|
|
|
|
|
|
|
|
_Cpy_base&
|
|
|
|
|
// Needs to use copy and swap for exception guarantees.
|
|
|
|
|
operator=(_Cpy_base const&) = delete;
|
|
|
|
|
};
|
|
|
|
|
} // namespace __polyfunc
|
|
|
|
|
/// @endcond
|
|
|
|
|
|
|
|
|
|
template<typename... _Signature>
|
|
|
|
|
class copyable_function; // not defined
|
|
|
|
|
|
|
|
|
|
template<typename _Tp>
|
|
|
|
|
constexpr bool __is_polymorphic_function_v<copyable_function<_Tp>> = true;
|
|
|
|
|
|
|
|
|
|
namespace __detail::__variant
|
|
|
|
|
{
|
|
|
|
|
template<typename> struct _Never_valueless_alt; // see <variant>
|
|
|
|
|
|
|
|
|
|
// Provide the strong exception-safety guarantee when emplacing a
|
|
|
|
|
// copyable_function into a variant.
|
|
|
|
|
template<typename... _Signature>
|
|
|
|
|
struct _Never_valueless_alt<std::copyable_function<_Signature...>>
|
|
|
|
|
: true_type
|
|
|
|
|
{ };
|
|
|
|
|
} // namespace __detail::__variant
|
|
|
|
|
#endif // __glibcxx_copyable_function
|
2022-06-23 18:42:55 +01:00
|
|
|
|
libstdc++: Implement C++26 function_ref [PR119126]
This patch implements C++26 function_ref as specified in P0792R14,
with correction for constraints for constructor accepting nontype_t
parameter from LWG 4256.
As function_ref may store a pointer to the const object, __Ptrs::_M_obj is
changed to const void*, so again we do not cast away const from const
objects. To help with necessary casts, a __polyfunc::__cast_to helper is
added, that accepts reference to or target type direclty.
The _Invoker now defines additional call methods used by function_ref:
_S_ptrs() for invoking target passed by reference, and __S_nttp, _S_bind_ptr,
_S_bind_ref for handling constructors accepting nontype_t. The existing
_S_call_storage is changed to thin wrapper, that initialies _Ptrs, and forwards
to _S_call_ptrs.
This reduced the most uses of _Storage::_M_ptr and _Storage::_M_ref,
so this functions was removed, and _Manager uses were adjusted.
Finally we make function_ref available in freestanding mode, as
move_only_function and copyable_function are currently only available in hosted,
so we define _Manager and _Mo_base only if either __glibcxx_move_only_function
or __glibcxx_copyable_function is defined.
PR libstdc++/119126
libstdc++-v3/ChangeLog:
* doc/doxygen/stdheader.cc: Added funcref_impl.h file.
* include/Makefile.am: Added funcref_impl.h file.
* include/Makefile.in: Added funcref_impl.h file.
* include/bits/funcref_impl.h: New file.
* include/bits/funcwrap.h: (_Ptrs::_M_obj): Const-qualify.
(_Storage::_M_ptr, _Storage::_M_ref): Remove.
(__polyfunc::__cast_to) Define.
(_Base_invoker::_S_ptrs, _Base_invoker::_S_nttp)
(_Base_invoker::_S_bind_ptrs, _Base_invoker::_S_bind_ref)
(_Base_invoker::_S_call_ptrs): Define.
(_Base_invoker::_S_call_storage): Foward to _S_call_ptrs.
(_Manager::_S_local, _Manager::_S_ptr): Adjust for _M_obj being
const qualified.
(__polyfunc::_Manager, __polyfunc::_Mo_base): Guard with
__glibcxx_move_only_function || __glibcxx_copyable_function.
(__polyfunc::__skip_first_arg, __polyfunc::__deduce_funcref)
(std::function_ref) [__glibcxx_function_ref]: Define.
* include/bits/utility.h (std::nontype_t, std::nontype)
(__is_nontype_v) [__glibcxx_function_ref]: Define.
* include/bits/version.def: Define function_ref.
* include/bits/version.h: Regenerate.
* include/std/functional: Define __cpp_lib_function_ref.
* src/c++23/std.cc.in (std::nontype_t, std::nontype)
(std::function_ref) [__cpp_lib_function_ref]: Export.
* testsuite/20_util/function_ref/assign.cc: New test.
* testsuite/20_util/function_ref/call.cc: New test.
* testsuite/20_util/function_ref/cons.cc: New test.
* testsuite/20_util/function_ref/cons_neg.cc: New test.
* testsuite/20_util/function_ref/conv.cc: New test.
* testsuite/20_util/function_ref/deduction.cc: New test.
* testsuite/20_util/function_ref/mutation.cc: New test.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-14 12:04:24 +02:00
|
|
|
#ifdef __glibcxx_function_ref // C++ >= 26
|
|
|
|
|
/// @cond undocumented
|
|
|
|
|
namespace __polyfunc
|
|
|
|
|
{
|
|
|
|
|
template<typename _Sig>
|
|
|
|
|
struct __skip_first_arg;
|
|
|
|
|
|
|
|
|
|
// Additional partial specializations are defined in bits/funcref_impl.h
|
|
|
|
|
template<bool _Noex, typename _Ret, typename _Arg, typename... _Args>
|
|
|
|
|
struct __skip_first_arg<_Ret(*)(_Arg, _Args...) noexcept(_Noex)>
|
|
|
|
|
{ using type = _Ret(_Args...) noexcept(_Noex); };
|
|
|
|
|
|
2025-09-23 08:54:28 +02:00
|
|
|
// Returns a function pointer to signature to be used with function_ref, or void.
|
libstdc++: Implement C++26 function_ref [PR119126]
This patch implements C++26 function_ref as specified in P0792R14,
with correction for constraints for constructor accepting nontype_t
parameter from LWG 4256.
As function_ref may store a pointer to the const object, __Ptrs::_M_obj is
changed to const void*, so again we do not cast away const from const
objects. To help with necessary casts, a __polyfunc::__cast_to helper is
added, that accepts reference to or target type direclty.
The _Invoker now defines additional call methods used by function_ref:
_S_ptrs() for invoking target passed by reference, and __S_nttp, _S_bind_ptr,
_S_bind_ref for handling constructors accepting nontype_t. The existing
_S_call_storage is changed to thin wrapper, that initialies _Ptrs, and forwards
to _S_call_ptrs.
This reduced the most uses of _Storage::_M_ptr and _Storage::_M_ref,
so this functions was removed, and _Manager uses were adjusted.
Finally we make function_ref available in freestanding mode, as
move_only_function and copyable_function are currently only available in hosted,
so we define _Manager and _Mo_base only if either __glibcxx_move_only_function
or __glibcxx_copyable_function is defined.
PR libstdc++/119126
libstdc++-v3/ChangeLog:
* doc/doxygen/stdheader.cc: Added funcref_impl.h file.
* include/Makefile.am: Added funcref_impl.h file.
* include/Makefile.in: Added funcref_impl.h file.
* include/bits/funcref_impl.h: New file.
* include/bits/funcwrap.h: (_Ptrs::_M_obj): Const-qualify.
(_Storage::_M_ptr, _Storage::_M_ref): Remove.
(__polyfunc::__cast_to) Define.
(_Base_invoker::_S_ptrs, _Base_invoker::_S_nttp)
(_Base_invoker::_S_bind_ptrs, _Base_invoker::_S_bind_ref)
(_Base_invoker::_S_call_ptrs): Define.
(_Base_invoker::_S_call_storage): Foward to _S_call_ptrs.
(_Manager::_S_local, _Manager::_S_ptr): Adjust for _M_obj being
const qualified.
(__polyfunc::_Manager, __polyfunc::_Mo_base): Guard with
__glibcxx_move_only_function || __glibcxx_copyable_function.
(__polyfunc::__skip_first_arg, __polyfunc::__deduce_funcref)
(std::function_ref) [__glibcxx_function_ref]: Define.
* include/bits/utility.h (std::nontype_t, std::nontype)
(__is_nontype_v) [__glibcxx_function_ref]: Define.
* include/bits/version.def: Define function_ref.
* include/bits/version.h: Regenerate.
* include/std/functional: Define __cpp_lib_function_ref.
* src/c++23/std.cc.in (std::nontype_t, std::nontype)
(std::function_ref) [__cpp_lib_function_ref]: Export.
* testsuite/20_util/function_ref/assign.cc: New test.
* testsuite/20_util/function_ref/call.cc: New test.
* testsuite/20_util/function_ref/cons.cc: New test.
* testsuite/20_util/function_ref/cons_neg.cc: New test.
* testsuite/20_util/function_ref/conv.cc: New test.
* testsuite/20_util/function_ref/deduction.cc: New test.
* testsuite/20_util/function_ref/mutation.cc: New test.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-14 12:04:24 +02:00
|
|
|
template<typename _Fn, typename _Tr>
|
|
|
|
|
consteval auto
|
|
|
|
|
__deduce_funcref()
|
|
|
|
|
{
|
|
|
|
|
if constexpr (is_member_object_pointer_v<_Fn>)
|
2025-09-23 08:54:28 +02:00
|
|
|
{
|
|
|
|
|
if constexpr (is_invocable_v<_Fn, _Tr>)
|
2025-10-20 15:19:43 +02:00
|
|
|
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
|
|
|
|
// 4425. CTAD function_ref from data member pointer should produce
|
|
|
|
|
// noexcept signature
|
|
|
|
|
return static_cast<invoke_result_t<_Fn, _Tr>(*)() noexcept>(nullptr);
|
2025-09-23 08:54:28 +02:00
|
|
|
}
|
|
|
|
|
else if constexpr (requires { typename __skip_first_arg<_Fn>::type; })
|
libstdc++: Implement C++26 function_ref [PR119126]
This patch implements C++26 function_ref as specified in P0792R14,
with correction for constraints for constructor accepting nontype_t
parameter from LWG 4256.
As function_ref may store a pointer to the const object, __Ptrs::_M_obj is
changed to const void*, so again we do not cast away const from const
objects. To help with necessary casts, a __polyfunc::__cast_to helper is
added, that accepts reference to or target type direclty.
The _Invoker now defines additional call methods used by function_ref:
_S_ptrs() for invoking target passed by reference, and __S_nttp, _S_bind_ptr,
_S_bind_ref for handling constructors accepting nontype_t. The existing
_S_call_storage is changed to thin wrapper, that initialies _Ptrs, and forwards
to _S_call_ptrs.
This reduced the most uses of _Storage::_M_ptr and _Storage::_M_ref,
so this functions was removed, and _Manager uses were adjusted.
Finally we make function_ref available in freestanding mode, as
move_only_function and copyable_function are currently only available in hosted,
so we define _Manager and _Mo_base only if either __glibcxx_move_only_function
or __glibcxx_copyable_function is defined.
PR libstdc++/119126
libstdc++-v3/ChangeLog:
* doc/doxygen/stdheader.cc: Added funcref_impl.h file.
* include/Makefile.am: Added funcref_impl.h file.
* include/Makefile.in: Added funcref_impl.h file.
* include/bits/funcref_impl.h: New file.
* include/bits/funcwrap.h: (_Ptrs::_M_obj): Const-qualify.
(_Storage::_M_ptr, _Storage::_M_ref): Remove.
(__polyfunc::__cast_to) Define.
(_Base_invoker::_S_ptrs, _Base_invoker::_S_nttp)
(_Base_invoker::_S_bind_ptrs, _Base_invoker::_S_bind_ref)
(_Base_invoker::_S_call_ptrs): Define.
(_Base_invoker::_S_call_storage): Foward to _S_call_ptrs.
(_Manager::_S_local, _Manager::_S_ptr): Adjust for _M_obj being
const qualified.
(__polyfunc::_Manager, __polyfunc::_Mo_base): Guard with
__glibcxx_move_only_function || __glibcxx_copyable_function.
(__polyfunc::__skip_first_arg, __polyfunc::__deduce_funcref)
(std::function_ref) [__glibcxx_function_ref]: Define.
* include/bits/utility.h (std::nontype_t, std::nontype)
(__is_nontype_v) [__glibcxx_function_ref]: Define.
* include/bits/version.def: Define function_ref.
* include/bits/version.h: Regenerate.
* include/std/functional: Define __cpp_lib_function_ref.
* src/c++23/std.cc.in (std::nontype_t, std::nontype)
(std::function_ref) [__cpp_lib_function_ref]: Export.
* testsuite/20_util/function_ref/assign.cc: New test.
* testsuite/20_util/function_ref/call.cc: New test.
* testsuite/20_util/function_ref/cons.cc: New test.
* testsuite/20_util/function_ref/cons_neg.cc: New test.
* testsuite/20_util/function_ref/conv.cc: New test.
* testsuite/20_util/function_ref/deduction.cc: New test.
* testsuite/20_util/function_ref/mutation.cc: New test.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-14 12:04:24 +02:00
|
|
|
return static_cast<__skip_first_arg<_Fn>::type*>(nullptr);
|
|
|
|
|
}
|
|
|
|
|
} // namespace __polyfunc
|
|
|
|
|
/// @endcond
|
|
|
|
|
|
|
|
|
|
template<typename... _Signature>
|
|
|
|
|
class function_ref; // not defined
|
|
|
|
|
|
|
|
|
|
template<typename _Fn>
|
|
|
|
|
requires is_function_v<_Fn>
|
|
|
|
|
function_ref(_Fn*) -> function_ref<_Fn>;
|
|
|
|
|
|
|
|
|
|
template<auto __f, class _Fn = remove_pointer_t<decltype(__f)>>
|
|
|
|
|
requires is_function_v<_Fn>
|
|
|
|
|
function_ref(nontype_t<__f>) -> function_ref<_Fn>;
|
|
|
|
|
|
2025-09-23 08:54:28 +02:00
|
|
|
template<auto __f, typename _Tp,
|
|
|
|
|
typename _SignaturePtr =
|
|
|
|
|
decltype(__polyfunc::__deduce_funcref<decltype(__f), _Tp&>())>
|
|
|
|
|
requires (!is_void_v<_SignaturePtr>)
|
libstdc++: Implement C++26 function_ref [PR119126]
This patch implements C++26 function_ref as specified in P0792R14,
with correction for constraints for constructor accepting nontype_t
parameter from LWG 4256.
As function_ref may store a pointer to the const object, __Ptrs::_M_obj is
changed to const void*, so again we do not cast away const from const
objects. To help with necessary casts, a __polyfunc::__cast_to helper is
added, that accepts reference to or target type direclty.
The _Invoker now defines additional call methods used by function_ref:
_S_ptrs() for invoking target passed by reference, and __S_nttp, _S_bind_ptr,
_S_bind_ref for handling constructors accepting nontype_t. The existing
_S_call_storage is changed to thin wrapper, that initialies _Ptrs, and forwards
to _S_call_ptrs.
This reduced the most uses of _Storage::_M_ptr and _Storage::_M_ref,
so this functions was removed, and _Manager uses were adjusted.
Finally we make function_ref available in freestanding mode, as
move_only_function and copyable_function are currently only available in hosted,
so we define _Manager and _Mo_base only if either __glibcxx_move_only_function
or __glibcxx_copyable_function is defined.
PR libstdc++/119126
libstdc++-v3/ChangeLog:
* doc/doxygen/stdheader.cc: Added funcref_impl.h file.
* include/Makefile.am: Added funcref_impl.h file.
* include/Makefile.in: Added funcref_impl.h file.
* include/bits/funcref_impl.h: New file.
* include/bits/funcwrap.h: (_Ptrs::_M_obj): Const-qualify.
(_Storage::_M_ptr, _Storage::_M_ref): Remove.
(__polyfunc::__cast_to) Define.
(_Base_invoker::_S_ptrs, _Base_invoker::_S_nttp)
(_Base_invoker::_S_bind_ptrs, _Base_invoker::_S_bind_ref)
(_Base_invoker::_S_call_ptrs): Define.
(_Base_invoker::_S_call_storage): Foward to _S_call_ptrs.
(_Manager::_S_local, _Manager::_S_ptr): Adjust for _M_obj being
const qualified.
(__polyfunc::_Manager, __polyfunc::_Mo_base): Guard with
__glibcxx_move_only_function || __glibcxx_copyable_function.
(__polyfunc::__skip_first_arg, __polyfunc::__deduce_funcref)
(std::function_ref) [__glibcxx_function_ref]: Define.
* include/bits/utility.h (std::nontype_t, std::nontype)
(__is_nontype_v) [__glibcxx_function_ref]: Define.
* include/bits/version.def: Define function_ref.
* include/bits/version.h: Regenerate.
* include/std/functional: Define __cpp_lib_function_ref.
* src/c++23/std.cc.in (std::nontype_t, std::nontype)
(std::function_ref) [__cpp_lib_function_ref]: Export.
* testsuite/20_util/function_ref/assign.cc: New test.
* testsuite/20_util/function_ref/call.cc: New test.
* testsuite/20_util/function_ref/cons.cc: New test.
* testsuite/20_util/function_ref/cons_neg.cc: New test.
* testsuite/20_util/function_ref/conv.cc: New test.
* testsuite/20_util/function_ref/deduction.cc: New test.
* testsuite/20_util/function_ref/mutation.cc: New test.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-14 12:04:24 +02:00
|
|
|
function_ref(nontype_t<__f>, _Tp&&)
|
2025-09-23 08:54:28 +02:00
|
|
|
-> function_ref<remove_pointer_t<_SignaturePtr>>;
|
libstdc++: Implement C++26 function_ref [PR119126]
This patch implements C++26 function_ref as specified in P0792R14,
with correction for constraints for constructor accepting nontype_t
parameter from LWG 4256.
As function_ref may store a pointer to the const object, __Ptrs::_M_obj is
changed to const void*, so again we do not cast away const from const
objects. To help with necessary casts, a __polyfunc::__cast_to helper is
added, that accepts reference to or target type direclty.
The _Invoker now defines additional call methods used by function_ref:
_S_ptrs() for invoking target passed by reference, and __S_nttp, _S_bind_ptr,
_S_bind_ref for handling constructors accepting nontype_t. The existing
_S_call_storage is changed to thin wrapper, that initialies _Ptrs, and forwards
to _S_call_ptrs.
This reduced the most uses of _Storage::_M_ptr and _Storage::_M_ref,
so this functions was removed, and _Manager uses were adjusted.
Finally we make function_ref available in freestanding mode, as
move_only_function and copyable_function are currently only available in hosted,
so we define _Manager and _Mo_base only if either __glibcxx_move_only_function
or __glibcxx_copyable_function is defined.
PR libstdc++/119126
libstdc++-v3/ChangeLog:
* doc/doxygen/stdheader.cc: Added funcref_impl.h file.
* include/Makefile.am: Added funcref_impl.h file.
* include/Makefile.in: Added funcref_impl.h file.
* include/bits/funcref_impl.h: New file.
* include/bits/funcwrap.h: (_Ptrs::_M_obj): Const-qualify.
(_Storage::_M_ptr, _Storage::_M_ref): Remove.
(__polyfunc::__cast_to) Define.
(_Base_invoker::_S_ptrs, _Base_invoker::_S_nttp)
(_Base_invoker::_S_bind_ptrs, _Base_invoker::_S_bind_ref)
(_Base_invoker::_S_call_ptrs): Define.
(_Base_invoker::_S_call_storage): Foward to _S_call_ptrs.
(_Manager::_S_local, _Manager::_S_ptr): Adjust for _M_obj being
const qualified.
(__polyfunc::_Manager, __polyfunc::_Mo_base): Guard with
__glibcxx_move_only_function || __glibcxx_copyable_function.
(__polyfunc::__skip_first_arg, __polyfunc::__deduce_funcref)
(std::function_ref) [__glibcxx_function_ref]: Define.
* include/bits/utility.h (std::nontype_t, std::nontype)
(__is_nontype_v) [__glibcxx_function_ref]: Define.
* include/bits/version.def: Define function_ref.
* include/bits/version.h: Regenerate.
* include/std/functional: Define __cpp_lib_function_ref.
* src/c++23/std.cc.in (std::nontype_t, std::nontype)
(std::function_ref) [__cpp_lib_function_ref]: Export.
* testsuite/20_util/function_ref/assign.cc: New test.
* testsuite/20_util/function_ref/call.cc: New test.
* testsuite/20_util/function_ref/cons.cc: New test.
* testsuite/20_util/function_ref/cons_neg.cc: New test.
* testsuite/20_util/function_ref/conv.cc: New test.
* testsuite/20_util/function_ref/deduction.cc: New test.
* testsuite/20_util/function_ref/mutation.cc: New test.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-14 12:04:24 +02:00
|
|
|
|
|
|
|
|
#endif // __glibcxx_function_ref
|
|
|
|
|
|
2021-10-06 13:28:57 +01:00
|
|
|
_GLIBCXX_END_NAMESPACE_VERSION
|
|
|
|
|
} // namespace std
|
|
|
|
|
|
libstdc++: Implement C++26 copyable_function [PR119125]
This patch implements C++26 copyable_function as specified in P2548R6.
It also implements LWG 4255 that adjust move_only_function so constructing
from empty copyable_function, produces empty functor. This falls from
existing checks, after specializing __is_polymorphic_function_v for
copyable_function specializations.
For compatible invoker signatures, the move_only_function may be constructed
from copyable_funciton without double indirection. To achieve that we derive
_Cpy_base from _Mo_base, and specialize __is_polymorphic_function_v for
copyable_function. Similary copyable_functions with compatible signatures
can be converted without double indirection.
As we starting to use _Op::_Copy operation from the _M_manage function,
invocations of that functions may now throw exceptions, so noexcept needs
to be removed from the signature of stored _M_manage pointers. This also
affects operations in _Mo_base, however we already wrap _M_manage invocations
in noexcept member functions (_M_move, _M_destroy, swap).
PR libstdc++/119125
libstdc++-v3/ChangeLog:
* doc/doxygen/stdheader.cc: Addded cpyfunc_impl.h header.
* include/Makefile.am: Add bits cpyfunc_impl.h.
* include/Makefile.in: Add bits cpyfunc_impl.h.
* include/bits/cpyfunc_impl.h: New file.
* include/bits/mofunc_impl.h: Mention LWG 4255.
* include/bits/move_only_function.h: Update header description
and change guard to also check __glibcxx_copyable_function.
(_Manager::_Func): Remove noexcept.
(std::__is_polymorphic_function_v<move_only_function<_Tp>>)
(__variant::_Never_valueless_alt<std::move_only_function<_Signature...>>)
(move_only_function) [__glibcxx_move_only_function]: Adjust guard.
(std::__is_polymorphic_function_v<copyable_function<_Tp>>)
(__variant::_Never_valueless_alt<std::copyable_function<_Signature...>>)
(__polyfunc::_Cpy_base, std::copyable_function)
[__glibcxx_copyable_function]: Define.
* include/bits/version.def: Define copyable_function.
* include/bits/version.h: Regenerate.
* include/std/functional: Define __cpp_lib_copyable_function.
* src/c++23/std.cc.in (copyable_function)
[__cpp_lib_copyable_function]: Export.
* testsuite/20_util/copyable_function/call.cc: New test based on
move_only_function tests.
* testsuite/20_util/copyable_function/cons.cc: New test based on
move_only_function tests.
* testsuite/20_util/copyable_function/conv.cc: New test based on
move_only_function tests.
* testsuite/20_util/copyable_function/copy.cc: New test.
* testsuite/20_util/copyable_function/move.cc: New test based on
move_only_function tests.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-12 10:01:22 +02:00
|
|
|
#ifdef __glibcxx_move_only_function // C++ >= 23 && HOSTED
|
2021-10-06 13:28:57 +01:00
|
|
|
#include "mofunc_impl.h"
|
|
|
|
|
#define _GLIBCXX_MOF_CV const
|
|
|
|
|
#include "mofunc_impl.h"
|
|
|
|
|
#define _GLIBCXX_MOF_REF &
|
|
|
|
|
#include "mofunc_impl.h"
|
|
|
|
|
#define _GLIBCXX_MOF_REF &&
|
|
|
|
|
#include "mofunc_impl.h"
|
|
|
|
|
#define _GLIBCXX_MOF_CV const
|
|
|
|
|
#define _GLIBCXX_MOF_REF &
|
|
|
|
|
#include "mofunc_impl.h"
|
|
|
|
|
#define _GLIBCXX_MOF_CV const
|
|
|
|
|
#define _GLIBCXX_MOF_REF &&
|
|
|
|
|
#include "mofunc_impl.h"
|
2023-09-19 17:46:32 +01:00
|
|
|
#endif // __glibcxx_move_only_function
|
libstdc++: Implement C++26 copyable_function [PR119125]
This patch implements C++26 copyable_function as specified in P2548R6.
It also implements LWG 4255 that adjust move_only_function so constructing
from empty copyable_function, produces empty functor. This falls from
existing checks, after specializing __is_polymorphic_function_v for
copyable_function specializations.
For compatible invoker signatures, the move_only_function may be constructed
from copyable_funciton without double indirection. To achieve that we derive
_Cpy_base from _Mo_base, and specialize __is_polymorphic_function_v for
copyable_function. Similary copyable_functions with compatible signatures
can be converted without double indirection.
As we starting to use _Op::_Copy operation from the _M_manage function,
invocations of that functions may now throw exceptions, so noexcept needs
to be removed from the signature of stored _M_manage pointers. This also
affects operations in _Mo_base, however we already wrap _M_manage invocations
in noexcept member functions (_M_move, _M_destroy, swap).
PR libstdc++/119125
libstdc++-v3/ChangeLog:
* doc/doxygen/stdheader.cc: Addded cpyfunc_impl.h header.
* include/Makefile.am: Add bits cpyfunc_impl.h.
* include/Makefile.in: Add bits cpyfunc_impl.h.
* include/bits/cpyfunc_impl.h: New file.
* include/bits/mofunc_impl.h: Mention LWG 4255.
* include/bits/move_only_function.h: Update header description
and change guard to also check __glibcxx_copyable_function.
(_Manager::_Func): Remove noexcept.
(std::__is_polymorphic_function_v<move_only_function<_Tp>>)
(__variant::_Never_valueless_alt<std::move_only_function<_Signature...>>)
(move_only_function) [__glibcxx_move_only_function]: Adjust guard.
(std::__is_polymorphic_function_v<copyable_function<_Tp>>)
(__variant::_Never_valueless_alt<std::copyable_function<_Signature...>>)
(__polyfunc::_Cpy_base, std::copyable_function)
[__glibcxx_copyable_function]: Define.
* include/bits/version.def: Define copyable_function.
* include/bits/version.h: Regenerate.
* include/std/functional: Define __cpp_lib_copyable_function.
* src/c++23/std.cc.in (copyable_function)
[__cpp_lib_copyable_function]: Export.
* testsuite/20_util/copyable_function/call.cc: New test based on
move_only_function tests.
* testsuite/20_util/copyable_function/cons.cc: New test based on
move_only_function tests.
* testsuite/20_util/copyable_function/conv.cc: New test based on
move_only_function tests.
* testsuite/20_util/copyable_function/copy.cc: New test.
* testsuite/20_util/copyable_function/move.cc: New test based on
move_only_function tests.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-12 10:01:22 +02:00
|
|
|
|
|
|
|
|
#ifdef __glibcxx_copyable_function // C++ >= 26 && HOSTED
|
|
|
|
|
#include "cpyfunc_impl.h"
|
|
|
|
|
#define _GLIBCXX_MOF_CV const
|
|
|
|
|
#include "cpyfunc_impl.h"
|
|
|
|
|
#define _GLIBCXX_MOF_REF &
|
|
|
|
|
#include "cpyfunc_impl.h"
|
|
|
|
|
#define _GLIBCXX_MOF_REF &&
|
|
|
|
|
#include "cpyfunc_impl.h"
|
|
|
|
|
#define _GLIBCXX_MOF_CV const
|
|
|
|
|
#define _GLIBCXX_MOF_REF &
|
|
|
|
|
#include "cpyfunc_impl.h"
|
|
|
|
|
#define _GLIBCXX_MOF_CV const
|
|
|
|
|
#define _GLIBCXX_MOF_REF &&
|
|
|
|
|
#include "cpyfunc_impl.h"
|
|
|
|
|
#endif // __glibcxx_copyable_function
|
|
|
|
|
|
libstdc++: Implement C++26 function_ref [PR119126]
This patch implements C++26 function_ref as specified in P0792R14,
with correction for constraints for constructor accepting nontype_t
parameter from LWG 4256.
As function_ref may store a pointer to the const object, __Ptrs::_M_obj is
changed to const void*, so again we do not cast away const from const
objects. To help with necessary casts, a __polyfunc::__cast_to helper is
added, that accepts reference to or target type direclty.
The _Invoker now defines additional call methods used by function_ref:
_S_ptrs() for invoking target passed by reference, and __S_nttp, _S_bind_ptr,
_S_bind_ref for handling constructors accepting nontype_t. The existing
_S_call_storage is changed to thin wrapper, that initialies _Ptrs, and forwards
to _S_call_ptrs.
This reduced the most uses of _Storage::_M_ptr and _Storage::_M_ref,
so this functions was removed, and _Manager uses were adjusted.
Finally we make function_ref available in freestanding mode, as
move_only_function and copyable_function are currently only available in hosted,
so we define _Manager and _Mo_base only if either __glibcxx_move_only_function
or __glibcxx_copyable_function is defined.
PR libstdc++/119126
libstdc++-v3/ChangeLog:
* doc/doxygen/stdheader.cc: Added funcref_impl.h file.
* include/Makefile.am: Added funcref_impl.h file.
* include/Makefile.in: Added funcref_impl.h file.
* include/bits/funcref_impl.h: New file.
* include/bits/funcwrap.h: (_Ptrs::_M_obj): Const-qualify.
(_Storage::_M_ptr, _Storage::_M_ref): Remove.
(__polyfunc::__cast_to) Define.
(_Base_invoker::_S_ptrs, _Base_invoker::_S_nttp)
(_Base_invoker::_S_bind_ptrs, _Base_invoker::_S_bind_ref)
(_Base_invoker::_S_call_ptrs): Define.
(_Base_invoker::_S_call_storage): Foward to _S_call_ptrs.
(_Manager::_S_local, _Manager::_S_ptr): Adjust for _M_obj being
const qualified.
(__polyfunc::_Manager, __polyfunc::_Mo_base): Guard with
__glibcxx_move_only_function || __glibcxx_copyable_function.
(__polyfunc::__skip_first_arg, __polyfunc::__deduce_funcref)
(std::function_ref) [__glibcxx_function_ref]: Define.
* include/bits/utility.h (std::nontype_t, std::nontype)
(__is_nontype_v) [__glibcxx_function_ref]: Define.
* include/bits/version.def: Define function_ref.
* include/bits/version.h: Regenerate.
* include/std/functional: Define __cpp_lib_function_ref.
* src/c++23/std.cc.in (std::nontype_t, std::nontype)
(std::function_ref) [__cpp_lib_function_ref]: Export.
* testsuite/20_util/function_ref/assign.cc: New test.
* testsuite/20_util/function_ref/call.cc: New test.
* testsuite/20_util/function_ref/cons.cc: New test.
* testsuite/20_util/function_ref/cons_neg.cc: New test.
* testsuite/20_util/function_ref/conv.cc: New test.
* testsuite/20_util/function_ref/deduction.cc: New test.
* testsuite/20_util/function_ref/mutation.cc: New test.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
2025-05-14 12:04:24 +02:00
|
|
|
#ifdef __glibcxx_function_ref // C++ >= 26
|
|
|
|
|
#include "funcref_impl.h"
|
|
|
|
|
#define _GLIBCXX_MOF_CV const
|
|
|
|
|
#include "funcref_impl.h"
|
|
|
|
|
#endif // __glibcxx_function_ref
|
|
|
|
|
|
|
|
|
|
#endif // move_only_function || copyable_function || function_ref
|
2025-05-12 11:06:34 +02:00
|
|
|
#endif // _GLIBCXX_FUNCWRAP_H
|