Hello, as usual thank you for the review. V2 is attached.
On 02/08/2024 14:38, Jonathan Wakely wrote:
On Fri, 2 Aug 2024 at 13:17, Jonathan Wakely <jwak...@redhat.com> wrote:On Fri, 2 Aug 2024 at 11:45, Giuseppe D'Angelo wrote:Hello, The attached patch adds support for P2248R8 + P3217R0 (Enabling list-initialization for algorithms, C++26). The big question is whether this keeps the code readable enough without introducing too much #ifdef-ery, so any feedback is appreciated.Putting the extra args on the algorithmfwd.h declarations is a nice way to avoid any clutter on the definitions. I think that is very readable. Another option would be to not touch those forward declarations, but add new ones with the defaults: #if __glibcxx_default_template_type_for_algorithm_values // new declarations with default template args ... #endif But I think what you've done is good.
I'll keep it then :)
For ranges_algo.h I'm almost tempted to say we should just treat this as a DR, to avoid the #ifdef-ery. Almost. Is there any reason we can't rearrange the template parameters fo C++20 and C++23 mode? I don't think users are allowed to use explicit template argument lists for invoke e.g. ranges::find.operator()<Iter, Proj> so it should be unobservable if we change the order for C++20 (and just don't add the default args until C++26). That might reduce the differences to just a line or two for each CPO.
Indeed, users cannot rely on any specific order of the template arguments when calling algorithms. This is
https://eel.is/c++draft/algorithms.requirements#15 which has this note:"Consequently, an implementation can declare an algorithm with different template parameters than those presented"
which of course does apply here: it's why P2248 could do these changes to begin with. The only reason why I kept them in the original order was a matter of caution, but sure, in the new patch I've changed them unconditionally and just used a macro to hide the default in pre-C++26 modes. This should keep the code clean(er).
The merged wording also removes the redundant 'typename' from the default arguments, but I think we might still need that for Clang compat. I'm not sure when Clang fully implemented "down with typename", but it was still causing issues some time last year.
I hope it's fine if I keep it. Thanks, -- Giuseppe D'Angelo
From 607c43341502b7f6e34a24e9f2ecbdaae504cf4e Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo <giuseppe.dang...@kdab.com> Date: Fri, 2 Aug 2024 00:23:04 +0200 Subject: [PATCH] libstdc++: add default template parameters to algorithms This implements P2248R8 + P3217R0, both approved for C++26. The changes are mostly mechanical; the struggle is to keep readability with the pre-P2248 signatures. * For containers, "classic STL" algorithms and their parallel versions, introduce a macro and amend their declarations/definitions with it. The macro either expands to the defaulted parameter or to nothing in pre-C++26 modes. * For range algorithms, we need to reorder their template parameters. I've done so unconditionally, because users cannot rely on template parameters of algorithms (this is explicitly authorized by [algorithms.requirements]/15). The defaults are then hidden behind another macro. libstdc++-v3/ChangeLog: * include/bits/iterator_concepts.h: Add projected_value_t. * include/bits/algorithmfwd.h: Add the default template parameter to the relevant forward declarations. * include/pstl/glue_algorithm_defs.h: Likewise. * include/bits/ranges_algo.h: Add the default template parameter to range-based algorithms. * include/bits/ranges_algobase.h: Likewise. * include/bits/ranges_util.h: Likewise. * include/bits/stl_iterator_base_types.h: Add helper macro. * include/bits/version.def: Add the new feature-testing macro. * include/bits/version.h: Regenerate. * include/std/algorithm: Pull the feature-testing macro. * include/std/ranges: Likewise. * include/std/deque: Pull the feature-testing macro, add the default for std::erase. * include/std/forward_list: Likewise. * include/std/list: Likewise. * include/std/string: Likewise. * include/std/vector: Likewise. * testsuite/23_containers/default_template_value.cc: New test. * testsuite/25_algorithms/default_template_value.cc: New test. Signed-off-by: Giuseppe D'Angelo <giuseppe.dang...@kdab.com> --- libstdc++-v3/include/bits/algorithmfwd.h | 61 ++++--- libstdc++-v3/include/bits/iterator_concepts.h | 7 + libstdc++-v3/include/bits/ranges_algo.h | 154 +++++++++++++----- libstdc++-v3/include/bits/ranges_algobase.h | 16 +- libstdc++-v3/include/bits/ranges_base.h | 9 + libstdc++-v3/include/bits/ranges_util.h | 10 +- .../include/bits/stl_iterator_base_types.h | 7 + libstdc++-v3/include/bits/version.def | 8 + libstdc++-v3/include/bits/version.h | 10 ++ .../include/pstl/glue_algorithm_defs.h | 23 +-- libstdc++-v3/include/std/algorithm | 1 + libstdc++-v3/include/std/deque | 4 +- libstdc++-v3/include/std/forward_list | 4 +- libstdc++-v3/include/std/list | 4 +- libstdc++-v3/include/std/ranges | 1 + libstdc++-v3/include/std/string | 4 +- libstdc++-v3/include/std/vector | 4 +- .../23_containers/default_template_value.cc | 40 +++++ .../25_algorithms/default_template_value.cc | 142 ++++++++++++++++ 19 files changed, 428 insertions(+), 81 deletions(-) create mode 100644 libstdc++-v3/testsuite/23_containers/default_template_value.cc create mode 100644 libstdc++-v3/testsuite/25_algorithms/default_template_value.cc diff --git a/libstdc++-v3/include/bits/algorithmfwd.h b/libstdc++-v3/include/bits/algorithmfwd.h index 34bf9921f43..88fac34e72f 100644 --- a/libstdc++-v3/include/bits/algorithmfwd.h +++ b/libstdc++-v3/include/bits/algorithmfwd.h @@ -203,12 +203,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION any_of(_IIter, _IIter, _Predicate); #endif - template<typename _FIter, typename _Tp> + template<typename _FIter, typename _Tp + _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_FIter)> _GLIBCXX20_CONSTEXPR bool binary_search(_FIter, _FIter, const _Tp&); - template<typename _FIter, typename _Tp, typename _Compare> + template<typename _FIter, typename _Tp + _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_FIter), + typename _Compare> _GLIBCXX20_CONSTEXPR bool binary_search(_FIter, _FIter, const _Tp&, _Compare); @@ -250,22 +253,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // count // count_if - template<typename _FIter, typename _Tp> + template<typename _FIter, typename _Tp + _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_FIter)> _GLIBCXX20_CONSTEXPR pair<_FIter, _FIter> equal_range(_FIter, _FIter, const _Tp&); - template<typename _FIter, typename _Tp, typename _Compare> + template<typename _FIter, typename _Tp + _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_FIter), + typename _Compare> _GLIBCXX20_CONSTEXPR pair<_FIter, _FIter> equal_range(_FIter, _FIter, const _Tp&, _Compare); - template<typename _FIter, typename _Tp> + template<typename _FIter, typename _Tp + _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_FIter)> _GLIBCXX20_CONSTEXPR void fill(_FIter, _FIter, const _Tp&); - template<typename _OIter, typename _Size, typename _Tp> + template<typename _OIter, typename _Size, typename _Tp + _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_OIter)> _GLIBCXX20_CONSTEXPR _OIter fill_n(_OIter, _Size, const _Tp&); @@ -377,12 +385,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void iter_swap(_FIter1, _FIter2); - template<typename _FIter, typename _Tp> + template<typename _FIter, typename _Tp + _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_FIter)> _GLIBCXX20_CONSTEXPR _FIter lower_bound(_FIter, _FIter, const _Tp&); - template<typename _FIter, typename _Tp, typename _Compare> + template<typename _FIter, typename _Tp + _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_FIter), + typename _Compare> _GLIBCXX20_CONSTEXPR _FIter lower_bound(_FIter, _FIter, const _Tp&, _Compare); @@ -553,7 +564,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // random_shuffle - template<typename _FIter, typename _Tp> + template<typename _FIter, typename _Tp + _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_FIter)> _GLIBCXX20_CONSTEXPR _FIter remove(_FIter, _FIter, const _Tp&); @@ -563,7 +575,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _FIter remove_if(_FIter, _FIter, _Predicate); - template<typename _IIter, typename _OIter, typename _Tp> + template<typename _IIter, typename _OIter, typename _Tp + _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_IIter)> _GLIBCXX20_CONSTEXPR _OIter remove_copy(_IIter, _IIter, _OIter, const _Tp&); @@ -580,7 +593,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _OIter replace_copy(_IIter, _IIter, _OIter, const _Tp&, const _Tp&); - template<typename _Iter, typename _OIter, typename _Predicate, typename _Tp> + template<typename _Iter, typename _OIter, typename _Predicate, typename _Tp + _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_OIter)> _GLIBCXX20_CONSTEXPR _OIter replace_copy_if(_Iter, _Iter, _OIter, _Predicate, const _Tp&); @@ -673,12 +687,15 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) // unique_copy - template<typename _FIter, typename _Tp> + template<typename _FIter, typename _Tp + _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_FIter)> _GLIBCXX20_CONSTEXPR _FIter upper_bound(_FIter, _FIter, const _Tp&); - template<typename _FIter, typename _Tp, typename _Compare> + template<typename _FIter, typename _Tp + _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_FIter), + typename _Compare> _GLIBCXX20_CONSTEXPR _FIter upper_bound(_FIter, _FIter, const _Tp&, _Compare); @@ -695,7 +712,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO _FIter adjacent_find(_FIter, _FIter, _BinaryPredicate); - template<typename _IIter, typename _Tp> + template<typename _IIter, typename _Tp + _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_IIter)> _GLIBCXX20_CONSTEXPR typename iterator_traits<_IIter>::difference_type count(_IIter, _IIter, const _Tp&); @@ -715,7 +733,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO bool equal(_IIter1, _IIter1, _IIter2, _BinaryPredicate); - template<typename _IIter, typename _Tp> + template<typename _IIter, typename _Tp + _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_IIter)> _GLIBCXX20_CONSTEXPR _IIter find(_IIter, _IIter, const _Tp&); @@ -843,12 +862,14 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO #endif #endif // HOSTED - template<typename _FIter, typename _Tp> + template<typename _FIter, typename _Tp + _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_FIter)> _GLIBCXX20_CONSTEXPR void replace(_FIter, _FIter, const _Tp&, const _Tp&); - template<typename _FIter, typename _Predicate, typename _Tp> + template<typename _FIter, typename _Predicate, typename _Tp + _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_FIter)> _GLIBCXX20_CONSTEXPR void replace_if(_FIter, _FIter, _Predicate, const _Tp&); @@ -863,12 +884,14 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO _FIter1 search(_FIter1, _FIter1, _FIter2, _FIter2, _BinaryPredicate); - template<typename _FIter, typename _Size, typename _Tp> + template<typename _FIter, typename _Size, typename _Tp + _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_FIter)> _GLIBCXX20_CONSTEXPR _FIter search_n(_FIter, _FIter, _Size, const _Tp&); - template<typename _FIter, typename _Size, typename _Tp, + template<typename _FIter, typename _Size, typename _Tp + _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_FIter), typename _BinaryPredicate> _GLIBCXX20_CONSTEXPR _FIter diff --git a/libstdc++-v3/include/bits/iterator_concepts.h b/libstdc++-v3/include/bits/iterator_concepts.h index ce0b8a10f88..4c5a9378d38 100644 --- a/libstdc++-v3/include/bits/iterator_concepts.h +++ b/libstdc++-v3/include/bits/iterator_concepts.h @@ -799,6 +799,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION indirectly_regular_unary_invocable<_Iter> _Proj> using projected = typename __detail::__projected<_Iter, _Proj>::__type; +#if __glibcxx_algorithm_default_value_type // C++ >= 26 + template<indirectly_readable _Iter, + indirectly_regular_unary_invocable<_Iter> _Proj> + using projected_value_t + = remove_cvref_t<invoke_result_t<_Proj&, iter_value_t<_Iter>&>>; +#endif + // [alg.req], common algorithm requirements /// [alg.req.ind.move], concept `indirectly_movable` diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h index d258be0b93f..9a117ae1ff1 100644 --- a/libstdc++-v3/include/bits/ranges_algo.h +++ b/libstdc++-v3/include/bits/ranges_algo.h @@ -281,7 +281,9 @@ namespace ranges struct __count_fn { template<input_iterator _Iter, sentinel_for<_Iter> _Sent, - typename _Tp, typename _Proj = identity> + typename _Proj = identity, + typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE_PROJ(_Iter, _Proj)> requires indirect_binary_predicate<ranges::equal_to, projected<_Iter, _Proj>, const _Tp*> @@ -296,7 +298,9 @@ namespace ranges return __n; } - template<input_range _Range, typename _Tp, typename _Proj = identity> + template<input_range _Range, typename _Proj = identity, + typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE_PROJ(iterator_t<_Range>, _Proj)> requires indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Range>, _Proj>, const _Tp*> @@ -344,8 +348,10 @@ namespace ranges struct __search_n_fn { - template<forward_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Tp, - typename _Pred = ranges::equal_to, typename _Proj = identity> + template<forward_iterator _Iter, sentinel_for<_Iter> _Sent, + typename _Pred = ranges::equal_to, typename _Proj = identity, + typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE_PROJ(_Iter, _Proj)> requires indirectly_comparable<_Iter, const _Tp*, _Pred, _Proj> constexpr subrange<_Iter> operator()(_Iter __first, _Sent __last, iter_difference_t<_Iter> __count, @@ -416,8 +422,10 @@ namespace ranges } } - template<forward_range _Range, typename _Tp, - typename _Pred = ranges::equal_to, typename _Proj = identity> + template<forward_range _Range, + typename _Pred = ranges::equal_to, typename _Proj = identity, + typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE_PROJ(iterator_t<_Range>, _Proj)> requires indirectly_comparable<iterator_t<_Range>, const _Tp*, _Pred, _Proj> constexpr borrowed_subrange_t<_Range> @@ -774,7 +782,11 @@ namespace ranges struct __replace_fn { template<input_iterator _Iter, sentinel_for<_Iter> _Sent, - typename _Tp1, typename _Tp2, typename _Proj = identity> + typename _Proj = identity, + typename _Tp1 + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE_PROJ(_Iter, _Proj), + typename _Tp2 + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE(_Tp1)> requires indirectly_writable<_Iter, const _Tp2&> && indirect_binary_predicate<ranges::equal_to, projected<_Iter, _Proj>, const _Tp1*> @@ -789,8 +801,11 @@ namespace ranges return __first; } - template<input_range _Range, - typename _Tp1, typename _Tp2, typename _Proj = identity> + template<input_range _Range, typename _Proj = identity, + typename _Tp1 + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE_PROJ(iterator_t<_Range>, _Proj), + typename _Tp2 + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE(_Tp1)> requires indirectly_writable<iterator_t<_Range>, const _Tp2&> && indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Range>, _Proj>, @@ -810,7 +825,9 @@ namespace ranges struct __replace_if_fn { template<input_iterator _Iter, sentinel_for<_Iter> _Sent, - typename _Tp, typename _Proj = identity, + typename _Proj = identity, + typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE_PROJ(_Iter, _Proj), indirect_unary_predicate<projected<_Iter, _Proj>> _Pred> requires indirectly_writable<_Iter, const _Tp&> constexpr _Iter @@ -823,7 +840,9 @@ namespace ranges return std::move(__first); } - template<input_range _Range, typename _Tp, typename _Proj = identity, + template<input_range _Range, typename _Proj = identity, + typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE_PROJ(iterator_t<_Range>, _Proj), indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred> requires indirectly_writable<iterator_t<_Range>, const _Tp&> @@ -844,11 +863,15 @@ namespace ranges struct __replace_copy_fn { template<input_iterator _Iter, sentinel_for<_Iter> _Sent, - typename _Tp1, typename _Tp2, output_iterator<const _Tp2&> _Out, - typename _Proj = identity> + typename _Out, typename _Proj = identity, + typename _Tp1 + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE_PROJ(_Iter, _Proj), + typename _Tp2 + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE(iter_value_t<_Out>)> requires indirectly_copyable<_Iter, _Out> && indirect_binary_predicate<ranges::equal_to, projected<_Iter, _Proj>, const _Tp1*> + && output_iterator<_Out, const _Tp2&> constexpr replace_copy_result<_Iter, _Out> operator()(_Iter __first, _Sent __last, _Out __result, const _Tp1& __old_value, const _Tp2& __new_value, @@ -862,12 +885,17 @@ namespace ranges return {std::move(__first), std::move(__result)}; } - template<input_range _Range, typename _Tp1, typename _Tp2, - output_iterator<const _Tp2&> _Out, typename _Proj = identity> + template<input_range _Range, typename _Out, + typename _Proj = identity, + typename _Tp1 + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE_PROJ(iterator_t<_Range>, _Proj), + typename _Tp2 + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE(iter_value_t<_Out>)> requires indirectly_copyable<iterator_t<_Range>, _Out> && indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Range>, _Proj>, const _Tp1*> + && output_iterator<_Out, const _Tp2&> constexpr replace_copy_result<borrowed_iterator_t<_Range>, _Out> operator()(_Range&& __r, _Out __result, const _Tp1& __old_value, const _Tp2& __new_value, @@ -887,10 +915,13 @@ namespace ranges struct __replace_copy_if_fn { template<input_iterator _Iter, sentinel_for<_Iter> _Sent, - typename _Tp, output_iterator<const _Tp&> _Out, + typename _Out, + typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE(iter_value_t<_Out>), typename _Proj = identity, indirect_unary_predicate<projected<_Iter, _Proj>> _Pred> requires indirectly_copyable<_Iter, _Out> + && output_iterator<_Out, const _Tp&> constexpr replace_copy_if_result<_Iter, _Out> operator()(_Iter __first, _Sent __last, _Out __result, _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) const @@ -904,11 +935,14 @@ namespace ranges } template<input_range _Range, - typename _Tp, output_iterator<const _Tp&> _Out, + typename _Out, + typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE(iter_value_t<_Out>), typename _Proj = identity, indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred> requires indirectly_copyable<iterator_t<_Range>, _Out> + && output_iterator<_Out, const _Tp&> constexpr replace_copy_if_result<borrowed_iterator_t<_Range>, _Out> operator()(_Range&& __r, _Out __result, _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) const @@ -1004,7 +1038,9 @@ namespace ranges struct __remove_fn { template<permutable _Iter, sentinel_for<_Iter> _Sent, - typename _Tp, typename _Proj = identity> + typename _Proj = identity, + typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE_PROJ(_Iter, _Proj)> requires indirect_binary_predicate<ranges::equal_to, projected<_Iter, _Proj>, const _Tp*> @@ -1019,7 +1055,9 @@ namespace ranges std::move(__pred), std::move(__proj)); } - template<forward_range _Range, typename _Tp, typename _Proj = identity> + template<forward_range _Range, typename _Proj = identity, + typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE_PROJ(iterator_t<_Range>, _Proj)> requires permutable<iterator_t<_Range>> && indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Range>, _Proj>, @@ -1079,7 +1117,9 @@ namespace ranges struct __remove_copy_fn { template<input_iterator _Iter, sentinel_for<_Iter> _Sent, - weakly_incrementable _Out, typename _Tp, typename _Proj = identity> + weakly_incrementable _Out, typename _Proj = identity, + typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE_PROJ(_Iter, _Proj)> requires indirectly_copyable<_Iter, _Out> && indirect_binary_predicate<ranges::equal_to, projected<_Iter, _Proj>, @@ -1098,7 +1138,9 @@ namespace ranges } template<input_range _Range, weakly_incrementable _Out, - typename _Tp, typename _Proj = identity> + typename _Proj = identity, + typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE_PROJ(iterator_t<_Range>, _Proj)> requires indirectly_copyable<iterator_t<_Range>, _Out> && indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Range>, _Proj>, @@ -2047,7 +2089,9 @@ namespace ranges struct __lower_bound_fn { template<forward_iterator _Iter, sentinel_for<_Iter> _Sent, - typename _Tp, typename _Proj = identity, + typename _Proj = identity, + typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE_PROJ(_Iter, _Proj), indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>> _Comp = ranges::less> constexpr _Iter @@ -2073,7 +2117,10 @@ namespace ranges return __first; } - template<forward_range _Range, typename _Tp, typename _Proj = identity, + template<forward_range _Range, + typename _Proj = identity, + typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE_PROJ(iterator_t<_Range>, _Proj), indirect_strict_weak_order<const _Tp*, projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less> @@ -2091,7 +2138,9 @@ namespace ranges struct __upper_bound_fn { template<forward_iterator _Iter, sentinel_for<_Iter> _Sent, - typename _Tp, typename _Proj = identity, + typename _Proj = identity, + typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE_PROJ(_Iter, _Proj), indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>> _Comp = ranges::less> constexpr _Iter @@ -2117,7 +2166,10 @@ namespace ranges return __first; } - template<forward_range _Range, typename _Tp, typename _Proj = identity, + template<forward_range _Range, + typename _Proj = identity, + typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE_PROJ(iterator_t<_Range>, _Proj), indirect_strict_weak_order<const _Tp*, projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less> @@ -2135,7 +2187,9 @@ namespace ranges struct __equal_range_fn { template<forward_iterator _Iter, sentinel_for<_Iter> _Sent, - typename _Tp, typename _Proj = identity, + typename _Proj = identity, + typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE_PROJ(_Iter, _Proj), indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>> _Comp = ranges::less> constexpr subrange<_Iter> @@ -2177,7 +2231,9 @@ namespace ranges } template<forward_range _Range, - typename _Tp, typename _Proj = identity, + typename _Proj = identity, + typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE_PROJ(iterator_t<_Range>, _Proj), indirect_strict_weak_order<const _Tp*, projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less> @@ -2195,7 +2251,9 @@ namespace ranges struct __binary_search_fn { template<forward_iterator _Iter, sentinel_for<_Iter> _Sent, - typename _Tp, typename _Proj = identity, + typename _Proj = identity, + typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE_PROJ(_Iter, _Proj), indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>> _Comp = ranges::less> constexpr bool @@ -2210,7 +2268,9 @@ namespace ranges } template<forward_range _Range, - typename _Tp, typename _Proj = identity, + typename _Proj = identity, + typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE_PROJ(iterator_t<_Range>, _Proj), indirect_strict_weak_order<const _Tp*, projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less> @@ -3469,14 +3529,19 @@ namespace ranges struct __contains_fn { template<input_iterator _Iter, sentinel_for<_Iter> _Sent, - typename _Tp, typename _Proj = identity> + typename _Proj = identity, + typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE_PROJ(_Iter, _Proj)> requires indirect_binary_predicate<ranges::equal_to, projected<_Iter, _Proj>, const _Tp*> constexpr bool operator()(_Iter __first, _Sent __last, const _Tp& __value, _Proj __proj = {}) const { return ranges::find(std::move(__first), __last, __value, std::move(__proj)) != __last; } - template<input_range _Range, typename _Tp, typename _Proj = identity> + template<input_range _Range, + typename _Proj = identity, + typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE_PROJ(iterator_t<_Range>, _Proj)> requires indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Range>, _Proj>, const _Tp*> constexpr bool @@ -3525,7 +3590,10 @@ namespace ranges struct __find_last_fn { - template<forward_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Tp, typename _Proj = identity> + template<forward_iterator _Iter, sentinel_for<_Iter> _Sent, + typename _Proj = identity, + typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE_PROJ(_Iter, _Proj)> requires indirect_binary_predicate<ranges::equal_to, projected<_Iter, _Proj>, const _Tp*> constexpr subrange<_Iter> operator()(_Iter __first, _Sent __last, const _Tp& __value, _Proj __proj = {}) const @@ -3556,7 +3624,9 @@ namespace ranges } } - template<forward_range _Range, typename _Tp, typename _Proj = identity> + template<forward_range _Range, typename _Proj = identity, + typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE_PROJ(iterator_t<_Range>, _Proj)> requires indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Range>, _Proj>, const _Tp*> constexpr borrowed_subrange_t<_Range> operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const @@ -3730,7 +3800,8 @@ namespace ranges return _Ret{std::move(__first), std::move(__accum)}; } - template<input_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Tp, + template<input_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE(iter_value_t<_Iter>), __detail::__indirectly_binary_left_foldable<_Tp, _Iter> _Fp> constexpr auto operator()(_Iter __first, _Sent __last, _Tp __init, _Fp __f) const @@ -3740,7 +3811,8 @@ namespace ranges std::move(__init), std::move(__f)); } - template<input_range _Range, typename _Tp, + template<input_range _Range, typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE(range_value_t<_Range>), __detail::__indirectly_binary_left_foldable<_Tp, iterator_t<_Range>> _Fp> constexpr auto operator()(_Range&& __r, _Tp __init, _Fp __f) const @@ -3755,7 +3827,8 @@ namespace ranges struct __fold_left_fn { - template<input_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Tp, + template<input_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE(iter_value_t<_Iter>), __detail::__indirectly_binary_left_foldable<_Tp, _Iter> _Fp> constexpr auto operator()(_Iter __first, _Sent __last, _Tp __init, _Fp __f) const @@ -3764,7 +3837,8 @@ namespace ranges std::move(__init), std::move(__f)).value; } - template<input_range _Range, typename _Tp, + template<input_range _Range, typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE(range_value_t<_Range>), __detail::__indirectly_binary_left_foldable<_Tp, iterator_t<_Range>> _Fp> constexpr auto operator()(_Range&& __r, _Tp __init, _Fp __f) const @@ -3842,7 +3916,8 @@ namespace ranges struct __fold_right_fn { - template<bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Tp, + template<bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE(iter_value_t<_Iter>), __detail::__indirectly_binary_right_foldable<_Tp, _Iter> _Fp> constexpr auto operator()(_Iter __first, _Sent __last, _Tp __init, _Fp __f) const @@ -3859,7 +3934,8 @@ namespace ranges return __accum; } - template<bidirectional_range _Range, typename _Tp, + template<bidirectional_range _Range, typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE(range_value_t<_Range>), __detail::__indirectly_binary_right_foldable<_Tp, iterator_t<_Range>> _Fp> constexpr auto operator()(_Range&& __r, _Tp __init, _Fp __f) const diff --git a/libstdc++-v3/include/bits/ranges_algobase.h b/libstdc++-v3/include/bits/ranges_algobase.h index fd35b8ba14c..39cf06bdd3e 100644 --- a/libstdc++-v3/include/bits/ranges_algobase.h +++ b/libstdc++-v3/include/bits/ranges_algobase.h @@ -536,7 +536,9 @@ namespace ranges struct __fill_n_fn { - template<typename _Tp, output_iterator<const _Tp&> _Out> + template<typename _Out, typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE(iter_value_t<_Out>)> + requires output_iterator<_Out, const _Tp&> constexpr _Out operator()(_Out __first, iter_difference_t<_Out> __n, const _Tp& __value) const @@ -581,8 +583,11 @@ namespace ranges struct __fill_fn { - template<typename _Tp, - output_iterator<const _Tp&> _Out, sentinel_for<_Out> _Sent> + template<typename _Out, + sentinel_for<_Out> _Sent, + typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE(iter_value_t<_Out>)> + requires output_iterator<_Out, const _Tp&> constexpr _Out operator()(_Out __first, _Sent __last, const _Tp& __value) const { @@ -608,7 +613,10 @@ namespace ranges } } - template<typename _Tp, output_range<const _Tp&> _Range> + template<typename _Range, + typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE(range_value_t<_Range>)> + requires output_range<_Range, const _Tp&> constexpr borrowed_iterator_t<_Range> operator()(_Range&& __r, const _Tp& __value) const { diff --git a/libstdc++-v3/include/bits/ranges_base.h b/libstdc++-v3/include/bits/ranges_base.h index 63eb552b48b..1a26df4c4c3 100644 --- a/libstdc++-v3/include/bits/ranges_base.h +++ b/libstdc++-v3/include/bits/ranges_base.h @@ -39,6 +39,15 @@ #include <bits/max_size_type.h> #include <bits/version.h> +#if __glibcxx_algorithm_default_value_type // C++ >= 26 +# define _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE(_X) = _X +# define _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE_PROJ(_I, _P) \ + = projected_value_t<_I, _P> +#else +# define _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE(_X) +# define _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE_PROJ(_I, _P) +#endif + #ifdef __cpp_lib_concepts namespace std _GLIBCXX_VISIBILITY(default) { diff --git a/libstdc++-v3/include/bits/ranges_util.h b/libstdc++-v3/include/bits/ranges_util.h index e6d96073e87..139c272046f 100644 --- a/libstdc++-v3/include/bits/ranges_util.h +++ b/libstdc++-v3/include/bits/ranges_util.h @@ -487,8 +487,10 @@ namespace ranges { struct __find_fn { - template<input_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Tp, - typename _Proj = identity> + template<input_iterator _Iter, sentinel_for<_Iter> _Sent, + typename _Proj = identity, + typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE_PROJ(_Iter, _Proj)> requires indirect_binary_predicate<ranges::equal_to, projected<_Iter, _Proj>, const _Tp*> constexpr _Iter @@ -521,7 +523,9 @@ namespace ranges return __first; } - template<input_range _Range, typename _Tp, typename _Proj = identity> + template<input_range _Range, typename _Proj = identity, + typename _Tp + _GLIBCXX26_RANGE_ALGORITHM_DEFAULT_VALUE_TYPE_PROJ(iterator_t<_Range>, _Proj)> requires indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Range>, _Proj>, const _Tp*> diff --git a/libstdc++-v3/include/bits/stl_iterator_base_types.h b/libstdc++-v3/include/bits/stl_iterator_base_types.h index 07beec3554d..2b87324eb77 100644 --- a/libstdc++-v3/include/bits/stl_iterator_base_types.h +++ b/libstdc++-v3/include/bits/stl_iterator_base_types.h @@ -269,4 +269,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_END_NAMESPACE_VERSION } // namespace +#if __glibcxx_algorithm_default_value_type // C++ >= 26 +# define _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_Iterator) \ + = typename iterator_traits<_Iterator>::value_type +#else +# define _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_It) +#endif + #endif /* _STL_ITERATOR_BASE_TYPES_H */ diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def index 47335bfa6dd..08dfd51c9db 100644 --- a/libstdc++-v3/include/bits/version.def +++ b/libstdc++-v3/include/bits/version.def @@ -1828,6 +1828,14 @@ ftms = { }; }; +ftms = { + name = algorithm_default_value_type; + values = { + v = 202403; + cxxmin = 26; + }; +}; + // Standard test specifications. stds[97] = ">= 199711L"; stds[03] = ">= 199711L"; diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h index defe54ac1f2..efd2c33aab7 100644 --- a/libstdc++-v3/include/bits/version.h +++ b/libstdc++-v3/include/bits/version.h @@ -2038,4 +2038,14 @@ #endif /* !defined(__cpp_lib_is_virtual_base_of) && defined(__glibcxx_want_is_virtual_base_of) */ #undef __glibcxx_want_is_virtual_base_of +#if !defined(__cpp_lib_algorithm_default_value_type) +# if (__cplusplus > 202302L) +# define __glibcxx_algorithm_default_value_type 202403L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_algorithm_default_value_type) +# define __cpp_lib_algorithm_default_value_type 202403L +# endif +# endif +#endif /* !defined(__cpp_lib_algorithm_default_value_type) && defined(__glibcxx_want_algorithm_default_value_type) */ +#undef __glibcxx_want_algorithm_default_value_type + #undef __glibcxx_want_all diff --git a/libstdc++-v3/include/pstl/glue_algorithm_defs.h b/libstdc++-v3/include/pstl/glue_algorithm_defs.h index cef78e22e31..cf997b5f3bc 100644 --- a/libstdc++-v3/include/pstl/glue_algorithm_defs.h +++ b/libstdc++-v3/include/pstl/glue_algorithm_defs.h @@ -10,6 +10,7 @@ #ifndef _PSTL_GLUE_ALGORITHM_DEFS_H #define _PSTL_GLUE_ALGORITHM_DEFS_H +#include <bits/stl_iterator_base_types.h> #include <bits/stl_pair.h> #include "execution_defs.h" @@ -55,7 +56,7 @@ template <class _ExecutionPolicy, class _ForwardIterator, class _Predicate> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> find_if_not(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Predicate __pred); -template <class _ExecutionPolicy, class _ForwardIterator, class _Tp> +template <class _ExecutionPolicy, class _ForwardIterator, class _Tp _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_ForwardIterator)> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> find(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value); @@ -95,7 +96,7 @@ adjacent_find(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardItera // [alg.count] -template <class _ExecutionPolicy, class _ForwardIterator, class _Tp> +template <class _ExecutionPolicy, class _ForwardIterator, class _Tp _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_ForwardIterator)> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, typename iterator_traits<_ForwardIterator>::difference_type> count(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value); @@ -117,12 +118,12 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardItera search(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __s_first, _ForwardIterator2 __s_last); -template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Tp, class _BinaryPredicate> +template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Tp _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_ForwardIterator), class _BinaryPredicate> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> search_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Size __count, const _Tp& __value, _BinaryPredicate __pred); -template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Tp> +template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Tp _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_ForwardIterator)> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> search_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Size __count, const _Tp& __value); @@ -164,17 +165,17 @@ transform(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _ForwardIterato // [alg.replace] -template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate, class _Tp> +template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate, class _Tp _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_ForwardIterator)> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> replace_if(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred, const _Tp& __new_value); -template <class _ExecutionPolicy, class _ForwardIterator, class _Tp> +template <class _ExecutionPolicy, class _ForwardIterator, class _Tp _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_ForwardIterator)> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> replace(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __old_value, const _Tp& __new_value); -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _UnaryPredicate, class _Tp> +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _UnaryPredicate, class _Tp _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_ForwardIterator2)> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> replace_copy_if(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __result, _UnaryPredicate __pred, const _Tp& __new_value); @@ -186,11 +187,11 @@ replace_copy(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardItera // [alg.fill] -template <class _ExecutionPolicy, class _ForwardIterator, class _Tp> +template <class _ExecutionPolicy, class _ForwardIterator, class _Tp _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_ForwardIterator)> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> fill(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value); -template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Tp> +template <class _ExecutionPolicy, class _ForwardIterator, class _Size, class _Tp _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_ForwardIterator)> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> fill_n(_ExecutionPolicy&& __exec, _ForwardIterator __first, _Size __count, const _Tp& __value); @@ -210,7 +211,7 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardItera remove_copy_if(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __result, _Predicate __pred); -template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp> +template <class _ExecutionPolicy, class _ForwardIterator1, class _ForwardIterator2, class _Tp _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_ForwardIterator1)> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> remove_copy(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIterator1 __last, _ForwardIterator2 __result, const _Tp& __value); @@ -219,7 +220,7 @@ template <class _ExecutionPolicy, class _ForwardIterator, class _UnaryPredicate> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> remove_if(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _UnaryPredicate __pred); -template <class _ExecutionPolicy, class _ForwardIterator, class _Tp> +template <class _ExecutionPolicy, class _ForwardIterator, class _Tp _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_ForwardIterator)> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator> remove(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value); diff --git a/libstdc++-v3/include/std/algorithm b/libstdc++-v3/include/std/algorithm index 163e6b5dca7..b410e7c281b 100644 --- a/libstdc++-v3/include/std/algorithm +++ b/libstdc++-v3/include/std/algorithm @@ -63,6 +63,7 @@ # include <bits/ranges_algo.h> #endif +#define __glibcxx_want_algorithm_default_value_type #define __glibcxx_want_clamp #define __glibcxx_want_constexpr_algorithms #define __glibcxx_want_freestanding_algorithm diff --git a/libstdc++-v3/include/std/deque b/libstdc++-v3/include/std/deque index 0bf8309c19a..76d07dbf30f 100644 --- a/libstdc++-v3/include/std/deque +++ b/libstdc++-v3/include/std/deque @@ -68,6 +68,7 @@ #include <bits/range_access.h> #include <bits/deque.tcc> +#define __glibcxx_want_algorithm_default_value_type #define __glibcxx_want_erase_if #define __glibcxx_want_nonmember_container_access #include <bits/version.h> @@ -115,7 +116,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return 0; } - template<typename _Tp, typename _Alloc, typename _Up> + template<typename _Tp, typename _Alloc, typename _Up + _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_Tp)> inline typename deque<_Tp, _Alloc>::size_type erase(deque<_Tp, _Alloc>& __cont, const _Up& __value) { diff --git a/libstdc++-v3/include/std/forward_list b/libstdc++-v3/include/std/forward_list index 5ac74360808..d91a86cc797 100644 --- a/libstdc++-v3/include/std/forward_list +++ b/libstdc++-v3/include/std/forward_list @@ -45,6 +45,7 @@ # include <debug/forward_list> #endif +#define __glibcxx_want_algorithm_default_value_type #define __glibcxx_want_erase_if #define __glibcxx_want_incomplete_container_elements #define __glibcxx_want_list_remove_return_type @@ -74,7 +75,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION erase_if(forward_list<_Tp, _Alloc>& __cont, _Predicate __pred) { return __cont.remove_if(__pred); } - template<typename _Tp, typename _Alloc, typename _Up> + template<typename _Tp, typename _Alloc, typename _Up + _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_Tp)> inline typename forward_list<_Tp, _Alloc>::size_type erase(forward_list<_Tp, _Alloc>& __cont, const _Up& __value) { diff --git a/libstdc++-v3/include/std/list b/libstdc++-v3/include/std/list index fce4e3d925b..08eb453f9e0 100644 --- a/libstdc++-v3/include/std/list +++ b/libstdc++-v3/include/std/list @@ -69,6 +69,7 @@ # include <debug/list> #endif +#define __glibcxx_want_algorithm_default_value_type #define __glibcxx_want_erase_if #define __glibcxx_want_incomplete_container_elements #define __glibcxx_want_list_remove_return_type @@ -98,7 +99,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION erase_if(list<_Tp, _Alloc>& __cont, _Predicate __pred) { return __cont.remove_if(__pred); } - template<typename _Tp, typename _Alloc, typename _Up> + template<typename _Tp, typename _Alloc, typename _Up + _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_Tp)> inline typename list<_Tp, _Alloc>::size_type erase(list<_Tp, _Alloc>& __cont, const _Up& __value) { diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index b7c7aa36ddc..a04c830f059 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -51,6 +51,7 @@ #include <bits/ranges_util.h> #include <bits/refwrap.h> +#define __glibcxx_want_algorithm_default_value_type #define __glibcxx_want_ranges #define __glibcxx_want_ranges_as_const #define __glibcxx_want_ranges_as_rvalue diff --git a/libstdc++-v3/include/std/string b/libstdc++-v3/include/std/string index 55144409cca..d8ad199b352 100644 --- a/libstdc++-v3/include/std/string +++ b/libstdc++-v3/include/std/string @@ -54,6 +54,7 @@ #include <bits/basic_string.h> #include <bits/basic_string.tcc> +#define __glibcxx_want_algorithm_default_value_type #define __glibcxx_want_constexpr_char_traits #define __glibcxx_want_constexpr_string #define __glibcxx_want_erase_if @@ -104,7 +105,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __osz - __cont.size(); } - template<typename _CharT, typename _Traits, typename _Alloc, typename _Up> + template<typename _CharT, typename _Traits, typename _Alloc, typename _Up + _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_CharT)> _GLIBCXX20_CONSTEXPR inline typename basic_string<_CharT, _Traits, _Alloc>::size_type erase(basic_string<_CharT, _Traits, _Alloc>& __cont, const _Up& __value) diff --git a/libstdc++-v3/include/std/vector b/libstdc++-v3/include/std/vector index a1f7ef86824..4e551408339 100644 --- a/libstdc++-v3/include/std/vector +++ b/libstdc++-v3/include/std/vector @@ -76,6 +76,7 @@ # include <debug/vector> #endif +#define __glibcxx_want_algorithm_default_value_type #define __glibcxx_want_constexpr_vector #define __glibcxx_want_erase_if #define __glibcxx_want_incomplete_container_elements @@ -128,7 +129,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return 0; } - template<typename _Tp, typename _Alloc, typename _Up> + template<typename _Tp, typename _Alloc, typename _Up + _GLIBCXX26_ALGORITHM_DEFAULT_VALUE_TYPE(_Tp)> _GLIBCXX20_CONSTEXPR inline typename vector<_Tp, _Alloc>::size_type erase(vector<_Tp, _Alloc>& __cont, const _Up& __value) diff --git a/libstdc++-v3/testsuite/23_containers/default_template_value.cc b/libstdc++-v3/testsuite/23_containers/default_template_value.cc new file mode 100644 index 00000000000..b7615032686 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/default_template_value.cc @@ -0,0 +1,40 @@ +// { dg-do compile { target c++26 } } + +#include <deque> +#include <forward_list> +#include <list> +#include <string> +#include <vector> + +#if !defined(__cpp_lib_algorithm_default_value_type) +#error "Feature test macro for default template type for algorithms' values is missing" +#elif __cpp_lib_algorithm_default_value_type < 202403L +#error "Feature test macro for default template type for algorithms' values is wrong" +#endif + +struct S { + S(int, double); + friend auto operator<=>(const S&, const S&) = default; +}; + +template<template<typename...> typename Container> +void test_erase() +{ + Container<S> c; + std::erase(c, {1, 3.14}); +} + +void +test() +{ + test_erase<std::deque>(); + test_erase<std::forward_list>(); + test_erase<std::list>(); + test_erase<std::vector>(); + + std::string s; + std::erase(s, {'x'}); + + std::wstring ws; + std::erase(ws, {L'x'}); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/default_template_value.cc b/libstdc++-v3/testsuite/25_algorithms/default_template_value.cc new file mode 100644 index 00000000000..3cf51bc087b --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/default_template_value.cc @@ -0,0 +1,142 @@ +// { dg-do compile { target c++26 } } + +#include <algorithm> + +#if !defined(__cpp_lib_algorithm_default_value_type) +#error "Feature test macro for default template type for algorithms' values is missing" +#elif __cpp_lib_algorithm_default_value_type < 202403L +#error "Feature test macro for default template type for algorithms' values is wrong" +#endif + +#include <execution> +#include <ranges> +#include <iterator> +#include <vector> + +// Conversions from Input to Output will be used in certain algorithms. +// Make Output have a different number of arguments to its constructor +// so we can check whether a braced-init-list is indeed matching Input +// or Output +struct Output +{ + Output(char, float, long); +}; + +#define OUTPUT_VAL {'x', 1.171f, 10L} + +struct Input +{ + Input(int, double); + friend bool operator<=>(const Input &, const Input &) = default; + friend Input operator+(const Input &, const Input &); + operator Output() const; +}; + +#define INPUT_VAL {1, 3.14} + +void +test() +{ + extern std::vector<Input> in; + extern std::vector<Output> out; + + const auto pred = [](auto &&) { return true; }; + + // [alg.find] + (void) std::find(in.begin(), in.end(), INPUT_VAL); + (void) std::find(std::execution::seq, in.begin(), in.end(), INPUT_VAL); + (void) std::ranges::find(in.begin(), in.end(), INPUT_VAL); + (void) std::ranges::find(in, INPUT_VAL); + + // [alg.count] + (void) std::count(in.begin(), in.end(), INPUT_VAL); + (void) std::count(std::execution::seq, in.begin(), in.end(), INPUT_VAL); + (void) std::ranges::count(in.begin(), in.end(), INPUT_VAL); + (void) std::ranges::count(in, INPUT_VAL); + + // [alg.search] + (void) std::search_n(in.begin(), in.end(), 10, INPUT_VAL); + (void) std::search_n(in.begin(), in.end(), 10, INPUT_VAL, std::equal_to{}); + (void) std::search_n(std::execution::seq, in.begin(), in.end(), 10, INPUT_VAL); + (void) std::search_n(std::execution::seq, in.begin(), in.end(), 10, INPUT_VAL, std::equal_to{}); + (void) std::ranges::search_n(in.begin(), in.end(), 10, INPUT_VAL); + (void) std::ranges::search_n(in, 10, INPUT_VAL); + + // [alg.replace] + (void) std::replace(in.begin(), in.end(), INPUT_VAL, INPUT_VAL); + (void) std::replace(std::execution::seq, in.begin(), in.end(), INPUT_VAL, INPUT_VAL); + (void) std::replace_if(in.begin(), in.end(), pred, INPUT_VAL); + (void) std::replace_if(std::execution::seq, in.begin(), in.end(), pred, INPUT_VAL); + + (void) std::ranges::replace(in.begin(), in.end(), INPUT_VAL, INPUT_VAL); + (void) std::ranges::replace(in, INPUT_VAL, INPUT_VAL); + (void) std::ranges::replace_if(in.begin(), in.end(), pred, INPUT_VAL); + (void) std::ranges::replace_if(in, pred, INPUT_VAL); + + (void) std::replace_copy_if(in.begin(), in.end(), out.begin(), pred, OUTPUT_VAL); + (void) std::replace_copy_if(std::execution::seq, in.begin(), in.end(), out.begin(), pred, OUTPUT_VAL); + (void) std::ranges::replace_copy_if(in.begin(), in.end(), out.begin(), pred, OUTPUT_VAL); + (void) std::ranges::replace_copy_if(in, out.begin(), pred, OUTPUT_VAL); + + // Non-range replace_copy is deliberately skipped by P2248 + (void) std::ranges::replace_copy(in.begin(), in.end(), out.begin(), INPUT_VAL, OUTPUT_VAL); + (void) std::ranges::replace_copy(in, out.begin(), INPUT_VAL, OUTPUT_VAL); + + // [alg.fill] + (void) std::fill(in.begin(), in.end(), INPUT_VAL); + (void) std::fill(std::execution::seq, in.begin(), in.end(), INPUT_VAL); + (void) std::ranges::fill(in.begin(), in.end(), INPUT_VAL); + (void) std::ranges::fill(in, INPUT_VAL); + + (void) std::fill_n(in.begin(), 10, INPUT_VAL); + (void) std::fill_n(std::execution::seq, in.begin(), 10, INPUT_VAL); + (void) std::ranges::fill_n(in.begin(), 10, INPUT_VAL); + + // [alg.remove] + (void) std::remove(in.begin(), in.end(), INPUT_VAL); + (void) std::remove(std::execution::seq, in.begin(), in.end(), INPUT_VAL); + (void) std::ranges::remove(in.begin(), in.end(), INPUT_VAL); + (void) std::ranges::remove(in, INPUT_VAL); + + (void) std::remove_copy(in.begin(), in.end(), out.begin(), INPUT_VAL); + (void) std::remove_copy(std::execution::seq, in.begin(), in.end(), out.begin(), INPUT_VAL); + (void) std::ranges::remove_copy(in.begin(), in.end(), out.begin(), INPUT_VAL); + (void) std::ranges::remove_copy(in, out.begin(), INPUT_VAL); + + // [alg.binary.search] + (void) std::lower_bound(in.begin(), in.end(), INPUT_VAL); + (void) std::lower_bound(in.begin(), in.end(), INPUT_VAL, std::less{}); + (void) std::ranges::lower_bound(in.begin(), in.end(), INPUT_VAL); + (void) std::ranges::lower_bound(in, INPUT_VAL); + + (void) std::upper_bound(in.begin(), in.end(), INPUT_VAL); + (void) std::upper_bound(in.begin(), in.end(), INPUT_VAL, std::less{}); + (void) std::ranges::upper_bound(in.begin(), in.end(), INPUT_VAL); + (void) std::ranges::upper_bound(in, INPUT_VAL); + + (void) std::equal_range(in.begin(), in.end(), INPUT_VAL); + (void) std::equal_range(in.begin(), in.end(), INPUT_VAL, std::less{}); + (void) std::ranges::equal_range(in.begin(), in.end(), INPUT_VAL); + (void) std::ranges::equal_range(in, INPUT_VAL); + + (void) std::binary_search(in.begin(), in.end(), INPUT_VAL); + (void) std::binary_search(in.begin(), in.end(), INPUT_VAL, std::less{}); + (void) std::ranges::binary_search(in.begin(), in.end(), INPUT_VAL); + (void) std::ranges::binary_search(in, INPUT_VAL); + + // [alg.fold] + (void) std::ranges::fold_left(in.begin(), in.end(), INPUT_VAL, std::plus<>{}); + (void) std::ranges::fold_left(in, INPUT_VAL, std::plus<>{}); + (void) std::ranges::fold_right(in.begin(), in.end(), INPUT_VAL, std::plus<>{}); + (void) std::ranges::fold_right(in, INPUT_VAL, std::plus<>{}); + (void) std::ranges::fold_left_with_iter(in.begin(), in.end(), INPUT_VAL, std::plus<>{}); + (void) std::ranges::fold_left_with_iter(in, INPUT_VAL, std::plus<>{}); + + // [alg.contains] + (void) std::ranges::contains(in.begin(), in.end(), INPUT_VAL); + (void) std::ranges::contains(in, INPUT_VAL); + + // [alg.find.last] + (void) std::ranges::find_last(in.begin(), in.end(), INPUT_VAL); + (void) std::ranges::find_last(in, INPUT_VAL); +} -- 2.34.1
smime.p7s
Description: S/MIME Cryptographic Signature