From 9f1a84548ecea9859c1f8d70c533e4e5a0701870 Mon Sep 17 00:00:00 2001
From: Giuseppe D'Angelo <giuseppe.dangelo@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, the change is simple and localized enough to justify
an ifdef on the feature testing macro;
* for "classic" algorithms and the parallel versions, introduce a
dedicated macro;
* range algorithms are more tricky as they usually require reordering
of the template parameters, and sometimes the introduction of new
constraints. The idea was to avoid too much surgery and try and keep
the code clean w.r.t. the pre-P2248 versions, even if sometimes this
means duplicating the template heads.
libstdc++-v3/ChangeLog:
* include/Makefile.am: Add the new header.
* include/Makefile.in: Regenerate.
* 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/version.def: Add the new feature-testing macro.
* include/bits/version.h (defined): 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.
* include/bits/stl_algorithm_default.h: New file. Adds a macro
to help with adding the default to the "classic STL" algorithms.
* 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.dangelo@kdab.com>
---
libstdc++-v3/include/Makefile.am | 1 +
libstdc++-v3/include/Makefile.in | 1 +
libstdc++-v3/include/bits/algorithmfwd.h | 62 +++--
libstdc++-v3/include/bits/iterator_concepts.h | 9 +
libstdc++-v3/include/bits/ranges_algo.h | 227 ++++++++++++++++--
libstdc++-v3/include/bits/ranges_algobase.h | 20 ++
libstdc++-v3/include/bits/ranges_util.h | 13 +
.../include/bits/stl_algorithm_default.h | 45 ++++
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 | 7 +-
libstdc++-v3/include/std/forward_list | 7 +-
libstdc++-v3/include/std/list | 7 +-
libstdc++-v3/include/std/ranges | 1 +
libstdc++-v3/include/std/string | 7 +-
libstdc++-v3/include/std/vector | 7 +-
.../23_containers/default_template_value.cc | 40 +++
.../25_algorithms/default_template_value.cc | 142 +++++++++++
20 files changed, 589 insertions(+), 49 deletions(-)
create mode 100644 libstdc++-v3/include/bits/stl_algorithm_default.h
create mode 100644 libstdc++-v3/testsuite/23_containers/default_template_value.cc
create mode 100644 libstdc++-v3/testsuite/25_algorithms/default_template_value.cc
@@ -149,6 +149,7 @@ bits_freestanding = \
${bits_srcdir}/sat_arith.h \
${bits_srcdir}/stl_algo.h \
${bits_srcdir}/stl_algobase.h \
+ ${bits_srcdir}/stl_algorithm_default.h \
${bits_srcdir}/stl_construct.h \
${bits_srcdir}/stl_function.h \
${bits_srcdir}/stl_iterator.h \
@@ -504,6 +504,7 @@ bits_freestanding = \
${bits_srcdir}/sat_arith.h \
${bits_srcdir}/stl_algo.h \
${bits_srcdir}/stl_algobase.h \
+ ${bits_srcdir}/stl_algorithm_default.h \
${bits_srcdir}/stl_construct.h \
${bits_srcdir}/stl_function.h \
${bits_srcdir}/stl_iterator.h \
@@ -33,6 +33,7 @@
#pragma GCC system_header
#include <bits/c++config.h>
+#include <bits/stl_algorithm_default.h>
#include <bits/stl_pair.h>
#include <bits/stl_iterator_base_types.h>
#if __cplusplus >= 201103L
@@ -203,12 +204,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
any_of(_IIter, _IIter, _Predicate);
#endif
- template<typename _FIter, typename _Tp>
+ template<typename _FIter, typename _Tp
+ _GLIBCXX26_DEFAULT_TEMPLATE_TYPE_FOR_ALGORITHM_VALUE(_FIter)>
_GLIBCXX20_CONSTEXPR
bool
binary_search(_FIter, _FIter, const _Tp&);
- template<typename _FIter, typename _Tp, typename _Compare>
+ template<typename _FIter, typename _Tp
+ _GLIBCXX26_DEFAULT_TEMPLATE_TYPE_FOR_ALGORITHM_VALUE(_FIter),
+ typename _Compare>
_GLIBCXX20_CONSTEXPR
bool
binary_search(_FIter, _FIter, const _Tp&, _Compare);
@@ -250,22 +254,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// count
// count_if
- template<typename _FIter, typename _Tp>
+ template<typename _FIter, typename _Tp
+ _GLIBCXX26_DEFAULT_TEMPLATE_TYPE_FOR_ALGORITHM_VALUE(_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_DEFAULT_TEMPLATE_TYPE_FOR_ALGORITHM_VALUE(_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_DEFAULT_TEMPLATE_TYPE_FOR_ALGORITHM_VALUE(_FIter)>
_GLIBCXX20_CONSTEXPR
void
fill(_FIter, _FIter, const _Tp&);
- template<typename _OIter, typename _Size, typename _Tp>
+ template<typename _OIter, typename _Size, typename _Tp
+ _GLIBCXX26_DEFAULT_TEMPLATE_TYPE_FOR_ALGORITHM_VALUE(_OIter)>
_GLIBCXX20_CONSTEXPR
_OIter
fill_n(_OIter, _Size, const _Tp&);
@@ -377,12 +386,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void
iter_swap(_FIter1, _FIter2);
- template<typename _FIter, typename _Tp>
+ template<typename _FIter, typename _Tp
+ _GLIBCXX26_DEFAULT_TEMPLATE_TYPE_FOR_ALGORITHM_VALUE(_FIter)>
_GLIBCXX20_CONSTEXPR
_FIter
lower_bound(_FIter, _FIter, const _Tp&);
- template<typename _FIter, typename _Tp, typename _Compare>
+ template<typename _FIter, typename _Tp
+ _GLIBCXX26_DEFAULT_TEMPLATE_TYPE_FOR_ALGORITHM_VALUE(_FIter),
+ typename _Compare>
_GLIBCXX20_CONSTEXPR
_FIter
lower_bound(_FIter, _FIter, const _Tp&, _Compare);
@@ -553,7 +565,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// random_shuffle
- template<typename _FIter, typename _Tp>
+ template<typename _FIter, typename _Tp
+ _GLIBCXX26_DEFAULT_TEMPLATE_TYPE_FOR_ALGORITHM_VALUE(_FIter)>
_GLIBCXX20_CONSTEXPR
_FIter
remove(_FIter, _FIter, const _Tp&);
@@ -563,7 +576,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_DEFAULT_TEMPLATE_TYPE_FOR_ALGORITHM_VALUE(_IIter)>
_GLIBCXX20_CONSTEXPR
_OIter
remove_copy(_IIter, _IIter, _OIter, const _Tp&);
@@ -580,7 +594,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_DEFAULT_TEMPLATE_TYPE_FOR_ALGORITHM_VALUE(_OIter)>
_GLIBCXX20_CONSTEXPR
_OIter
replace_copy_if(_Iter, _Iter, _OIter, _Predicate, const _Tp&);
@@ -673,12 +688,15 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
// unique_copy
- template<typename _FIter, typename _Tp>
+ template<typename _FIter, typename _Tp
+ _GLIBCXX26_DEFAULT_TEMPLATE_TYPE_FOR_ALGORITHM_VALUE(_FIter)>
_GLIBCXX20_CONSTEXPR
_FIter
upper_bound(_FIter, _FIter, const _Tp&);
- template<typename _FIter, typename _Tp, typename _Compare>
+ template<typename _FIter, typename _Tp
+ _GLIBCXX26_DEFAULT_TEMPLATE_TYPE_FOR_ALGORITHM_VALUE(_FIter),
+ typename _Compare>
_GLIBCXX20_CONSTEXPR
_FIter
upper_bound(_FIter, _FIter, const _Tp&, _Compare);
@@ -695,7 +713,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
_FIter
adjacent_find(_FIter, _FIter, _BinaryPredicate);
- template<typename _IIter, typename _Tp>
+ template<typename _IIter, typename _Tp
+ _GLIBCXX26_DEFAULT_TEMPLATE_TYPE_FOR_ALGORITHM_VALUE(_IIter)>
_GLIBCXX20_CONSTEXPR
typename iterator_traits<_IIter>::difference_type
count(_IIter, _IIter, const _Tp&);
@@ -715,7 +734,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
bool
equal(_IIter1, _IIter1, _IIter2, _BinaryPredicate);
- template<typename _IIter, typename _Tp>
+ template<typename _IIter, typename _Tp
+ _GLIBCXX26_DEFAULT_TEMPLATE_TYPE_FOR_ALGORITHM_VALUE(_IIter)>
_GLIBCXX20_CONSTEXPR
_IIter
find(_IIter, _IIter, const _Tp&);
@@ -843,12 +863,14 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
#endif
#endif // HOSTED
- template<typename _FIter, typename _Tp>
+ template<typename _FIter, typename _Tp
+ _GLIBCXX26_DEFAULT_TEMPLATE_TYPE_FOR_ALGORITHM_VALUE(_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_DEFAULT_TEMPLATE_TYPE_FOR_ALGORITHM_VALUE(_FIter)>
_GLIBCXX20_CONSTEXPR
void
replace_if(_FIter, _FIter, _Predicate, const _Tp&);
@@ -863,12 +885,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_DEFAULT_TEMPLATE_TYPE_FOR_ALGORITHM_VALUE(_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_DEFAULT_TEMPLATE_TYPE_FOR_ALGORITHM_VALUE(_FIter),
typename _BinaryPredicate>
_GLIBCXX20_CONSTEXPR
_FIter
@@ -37,6 +37,9 @@
#include <bits/ptr_traits.h> // to_address
#include <bits/ranges_cmp.h> // identity, ranges::less
+#define __glibcxx_want_default_template_type_for_algorithm_values
+#include <bits/version.h>
+
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -799,6 +802,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
indirectly_regular_unary_invocable<_Iter> _Proj>
using projected = typename __detail::__projected<_Iter, _Proj>::__type;
+#if __glibcxx_default_template_type_for_algorithm_values // 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`
@@ -39,6 +39,9 @@
#include <bits/ranges_util.h>
#include <bits/uniform_int_dist.h> // concept uniform_random_bit_generator
+#define __glibcxx_want_default_template_type_for_algorithm_values
+#include <bits/version.h>
+
#if __glibcxx_concepts
namespace std _GLIBCXX_VISIBILITY(default)
{
@@ -280,8 +283,13 @@ namespace ranges
struct __count_fn
{
+#if __glibcxx_default_template_type_for_algorithm_values
+ template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Proj = identity, typename _Tp = projected_value_t<_Iter, _Proj>>
+#else
template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
typename _Tp, typename _Proj = identity>
+#endif
requires indirect_binary_predicate<ranges::equal_to,
projected<_Iter, _Proj>,
const _Tp*>
@@ -296,7 +304,12 @@ namespace ranges
return __n;
}
+#if __glibcxx_default_template_type_for_algorithm_values
+ template<input_range _Range, typename _Proj = identity,
+ typename _Tp = projected_value_t<iterator_t<_Range>, _Proj>>
+#else
template<input_range _Range, typename _Tp, typename _Proj = identity>
+#endif
requires indirect_binary_predicate<ranges::equal_to,
projected<iterator_t<_Range>, _Proj>,
const _Tp*>
@@ -344,8 +357,14 @@ namespace ranges
struct __search_n_fn
{
+#if __glibcxx_default_template_type_for_algorithm_values
+ template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Pred = ranges::equal_to, typename _Proj = identity,
+ typename _Tp = projected_value_t<_Iter, _Proj>>
+#else
template<forward_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Tp,
typename _Pred = ranges::equal_to, typename _Proj = identity>
+#endif
requires indirectly_comparable<_Iter, const _Tp*, _Pred, _Proj>
constexpr subrange<_Iter>
operator()(_Iter __first, _Sent __last, iter_difference_t<_Iter> __count,
@@ -416,8 +435,14 @@ namespace ranges
}
}
+#if __glibcxx_default_template_type_for_algorithm_values
+ template<forward_range _Range,
+ typename _Pred = ranges::equal_to, typename _Proj = identity,
+ typename _Tp = projected_value_t<iterator_t<_Range>, _Proj>>
+#else
template<forward_range _Range, typename _Tp,
typename _Pred = ranges::equal_to, typename _Proj = identity>
+#endif
requires indirectly_comparable<iterator_t<_Range>, const _Tp*,
_Pred, _Proj>
constexpr borrowed_subrange_t<_Range>
@@ -773,8 +798,15 @@ namespace ranges
struct __replace_fn
{
+#if __glibcxx_default_template_type_for_algorithm_values
+ template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Proj = identity,
+ typename _Tp1 = projected_value_t<_Iter, _Proj>,
+ typename _Tp2 = _Tp1>
+#else
template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
typename _Tp1, typename _Tp2, typename _Proj = identity>
+#endif
requires indirectly_writable<_Iter, const _Tp2&>
&& indirect_binary_predicate<ranges::equal_to, projected<_Iter, _Proj>,
const _Tp1*>
@@ -789,8 +821,14 @@ namespace ranges
return __first;
}
+#if __glibcxx_default_template_type_for_algorithm_values
+ template<input_range _Range, typename _Proj = identity,
+ typename _Tp1 = projected_value_t<iterator_t<_Range>, _Proj>,
+ typename _Tp2 = _Tp1>
+#else
template<input_range _Range,
typename _Tp1, typename _Tp2, typename _Proj = identity>
+#endif
requires indirectly_writable<iterator_t<_Range>, const _Tp2&>
&& indirect_binary_predicate<ranges::equal_to,
projected<iterator_t<_Range>, _Proj>,
@@ -809,9 +847,16 @@ namespace ranges
struct __replace_if_fn
{
+#if __glibcxx_default_template_type_for_algorithm_values
+ template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Proj = identity,
+ typename _Tp = projected_value_t<_Iter, _Proj>,
+ indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
+#else
template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
typename _Tp, typename _Proj = identity,
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
+#endif
requires indirectly_writable<_Iter, const _Tp&>
constexpr _Iter
operator()(_Iter __first, _Sent __last,
@@ -823,9 +868,16 @@ namespace ranges
return std::move(__first);
}
+#if __glibcxx_default_template_type_for_algorithm_values
+ template<input_range _Range, typename _Proj = identity,
+ typename _Tp = projected_value_t<iterator_t<_Range>, _Proj>,
+ indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
+ _Pred>
+#else
template<input_range _Range, typename _Tp, typename _Proj = identity,
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
_Pred>
+#endif
requires indirectly_writable<iterator_t<_Range>, const _Tp&>
constexpr borrowed_iterator_t<_Range>
operator()(_Range&& __r,
@@ -843,12 +895,22 @@ namespace ranges
struct __replace_copy_fn
{
+#if __glibcxx_default_template_type_for_algorithm_values
+ template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Out, typename _Proj = identity,
+ typename _Tp1 = projected_value_t<_Iter, _Proj>,
+ typename _Tp2 = iter_value_t<_Out>>
+#else
template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
typename _Tp1, typename _Tp2, output_iterator<const _Tp2&> _Out,
typename _Proj = identity>
+#endif
requires indirectly_copyable<_Iter, _Out>
&& indirect_binary_predicate<ranges::equal_to,
projected<_Iter, _Proj>, const _Tp1*>
+#if __glibcxx_default_template_type_for_algorithm_values
+ && output_iterator<_Out, const _Tp2&>
+#endif
constexpr replace_copy_result<_Iter, _Out>
operator()(_Iter __first, _Sent __last, _Out __result,
const _Tp1& __old_value, const _Tp2& __new_value,
@@ -862,12 +924,22 @@ namespace ranges
return {std::move(__first), std::move(__result)};
}
+#if __glibcxx_default_template_type_for_algorithm_values
+ template<input_range _Range, typename _Out,
+ typename _Proj = identity,
+ typename _Tp1 = projected_value_t<iterator_t<_Range>, _Proj>,
+ typename _Tp2 = iter_value_t<_Out>>
+#else
template<input_range _Range, typename _Tp1, typename _Tp2,
output_iterator<const _Tp2&> _Out, typename _Proj = identity>
+#endif
requires indirectly_copyable<iterator_t<_Range>, _Out>
&& indirect_binary_predicate<ranges::equal_to,
projected<iterator_t<_Range>, _Proj>,
const _Tp1*>
+#if __glibcxx_default_template_type_for_algorithm_values
+ && output_iterator<_Out, const _Tp2&>
+#endif
constexpr replace_copy_result<borrowed_iterator_t<_Range>, _Out>
operator()(_Range&& __r, _Out __result,
const _Tp1& __old_value, const _Tp2& __new_value,
@@ -886,11 +958,21 @@ namespace ranges
struct __replace_copy_if_fn
{
+#if __glibcxx_default_template_type_for_algorithm_values
+ template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Out, typename _Tp = iter_value_t<_Out>,
+ typename _Proj = identity,
+ indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
+#else
template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
typename _Tp, output_iterator<const _Tp&> _Out,
typename _Proj = identity,
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
+#endif
requires indirectly_copyable<_Iter, _Out>
+#if __glibcxx_default_template_type_for_algorithm_values
+ && output_iterator<_Out, const _Tp&>
+#endif
constexpr replace_copy_if_result<_Iter, _Out>
operator()(_Iter __first, _Sent __last, _Out __result,
_Pred __pred, const _Tp& __new_value, _Proj __proj = {}) const
@@ -903,12 +985,23 @@ namespace ranges
return {std::move(__first), std::move(__result)};
}
+#if __glibcxx_default_template_type_for_algorithm_values
+ template<input_range _Range,
+ typename _Out, typename _Tp = iter_value_t<_Out>,
+ typename _Proj = identity,
+ indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
+ _Pred>
+#else
template<input_range _Range,
typename _Tp, output_iterator<const _Tp&> _Out,
typename _Proj = identity,
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
_Pred>
+#endif
requires indirectly_copyable<iterator_t<_Range>, _Out>
+#if __glibcxx_default_template_type_for_algorithm_values
+ && output_iterator<_Out, const _Tp&>
+#endif
constexpr replace_copy_if_result<borrowed_iterator_t<_Range>, _Out>
operator()(_Range&& __r, _Out __result,
_Pred __pred, const _Tp& __new_value, _Proj __proj = {}) const
@@ -1003,8 +1096,14 @@ namespace ranges
struct __remove_fn
{
+#if __glibcxx_default_template_type_for_algorithm_values
+ template<permutable _Iter, sentinel_for<_Iter> _Sent,
+ typename _Proj = identity,
+ typename _Tp = projected_value_t<_Iter, _Proj>>
+#else
template<permutable _Iter, sentinel_for<_Iter> _Sent,
typename _Tp, typename _Proj = identity>
+#endif
requires indirect_binary_predicate<ranges::equal_to,
projected<_Iter, _Proj>,
const _Tp*>
@@ -1019,7 +1118,12 @@ namespace ranges
std::move(__pred), std::move(__proj));
}
+#if __glibcxx_default_template_type_for_algorithm_values
+ template<forward_range _Range, typename _Proj = identity,
+ typename _Tp = projected_value_t<iterator_t<_Range>, _Proj>>
+#else
template<forward_range _Range, typename _Tp, typename _Proj = identity>
+#endif
requires permutable<iterator_t<_Range>>
&& indirect_binary_predicate<ranges::equal_to,
projected<iterator_t<_Range>, _Proj>,
@@ -1078,8 +1182,14 @@ namespace ranges
struct __remove_copy_fn
{
+#if __glibcxx_default_template_type_for_algorithm_values
+ template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
+ weakly_incrementable _Out, typename _Proj = identity,
+ typename _Tp = projected_value_t<_Iter, _Proj>>
+#else
template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
weakly_incrementable _Out, typename _Tp, typename _Proj = identity>
+#endif
requires indirectly_copyable<_Iter, _Out>
&& indirect_binary_predicate<ranges::equal_to,
projected<_Iter, _Proj>,
@@ -1097,8 +1207,14 @@ namespace ranges
return {std::move(__first), std::move(__result)};
}
+#if __glibcxx_default_template_type_for_algorithm_values
+ template<input_range _Range, weakly_incrementable _Out,
+ typename _Proj = identity,
+ typename _Tp = projected_value_t<iterator_t<_Range>, _Proj>>
+#else
template<input_range _Range, weakly_incrementable _Out,
typename _Tp, typename _Proj = identity>
+#endif
requires indirectly_copyable<iterator_t<_Range>, _Out>
&& indirect_binary_predicate<ranges::equal_to,
projected<iterator_t<_Range>, _Proj>,
@@ -2047,7 +2163,12 @@ namespace ranges
struct __lower_bound_fn
{
template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
+#if __glibcxx_default_template_type_for_algorithm_values
+ typename _Proj = identity,
+ typename _Tp = projected_value_t<_Iter, _Proj>,
+#else
typename _Tp, typename _Proj = identity,
+#endif
indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>>
_Comp = ranges::less>
constexpr _Iter
@@ -2073,7 +2194,13 @@ namespace ranges
return __first;
}
- template<forward_range _Range, typename _Tp, typename _Proj = identity,
+ template<forward_range _Range,
+#if __glibcxx_default_template_type_for_algorithm_values
+ typename _Proj = identity,
+ typename _Tp = projected_value_t<iterator_t<_Range>, _Proj>,
+#else
+ typename _Tp, typename _Proj = identity,
+#endif
indirect_strict_weak_order<const _Tp*,
projected<iterator_t<_Range>, _Proj>>
_Comp = ranges::less>
@@ -2091,7 +2218,12 @@ namespace ranges
struct __upper_bound_fn
{
template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
+#if __glibcxx_default_template_type_for_algorithm_values
+ typename _Proj = identity,
+ typename _Tp = projected_value_t<_Iter, _Proj>,
+#else
typename _Tp, typename _Proj = identity,
+#endif
indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>>
_Comp = ranges::less>
constexpr _Iter
@@ -2117,7 +2249,13 @@ namespace ranges
return __first;
}
- template<forward_range _Range, typename _Tp, typename _Proj = identity,
+ template<forward_range _Range,
+#if __glibcxx_default_template_type_for_algorithm_values
+ typename _Proj = identity,
+ typename _Tp = projected_value_t<iterator_t<_Range>, _Proj>,
+#else
+ typename _Tp, typename _Proj = identity,
+#endif
indirect_strict_weak_order<const _Tp*,
projected<iterator_t<_Range>, _Proj>>
_Comp = ranges::less>
@@ -2135,7 +2273,12 @@ namespace ranges
struct __equal_range_fn
{
template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
+#if __glibcxx_default_template_type_for_algorithm_values
+ typename _Proj = identity,
+ typename _Tp = projected_value_t<_Iter, _Proj>,
+#else
typename _Tp, typename _Proj = identity,
+#endif
indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>>
_Comp = ranges::less>
constexpr subrange<_Iter>
@@ -2177,7 +2320,12 @@ namespace ranges
}
template<forward_range _Range,
+#if __glibcxx_default_template_type_for_algorithm_values
+ typename _Proj = identity,
+ typename _Tp = projected_value_t<iterator_t<_Range>, _Proj>,
+#else
typename _Tp, typename _Proj = identity,
+#endif
indirect_strict_weak_order<const _Tp*,
projected<iterator_t<_Range>, _Proj>>
_Comp = ranges::less>
@@ -2195,7 +2343,12 @@ namespace ranges
struct __binary_search_fn
{
template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
+#if __glibcxx_default_template_type_for_algorithm_values
+ typename _Proj = identity,
+ typename _Tp = projected_value_t<_Iter, _Proj>,
+#else
typename _Tp, typename _Proj = identity,
+#endif
indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>>
_Comp = ranges::less>
constexpr bool
@@ -2210,7 +2363,12 @@ namespace ranges
}
template<forward_range _Range,
+#if __glibcxx_default_template_type_for_algorithm_values
+ typename _Proj = identity,
+ typename _Tp = projected_value_t<iterator_t<_Range>, _Proj>,
+#else
typename _Tp, typename _Proj = identity,
+#endif
indirect_strict_weak_order<const _Tp*,
projected<iterator_t<_Range>, _Proj>>
_Comp = ranges::less>
@@ -3468,15 +3626,27 @@ namespace ranges
#if __glibcxx_ranges_contains >= 202207L // C++ >= 23
struct __contains_fn
{
+#if __glibcxx_default_template_type_for_algorithm_values
+ template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Proj = identity,
+ typename _Tp = projected_value_t<_Iter, _Proj>>
+#else
template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
typename _Tp, typename _Proj = identity>
+#endif
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; }
+#if __glibcxx_default_template_type_for_algorithm_values
+ template<input_range _Range,
+ typename _Proj = identity,
+ typename _Tp = projected_value_t<iterator_t<_Range>, _Proj>>
+#else
template<input_range _Range, typename _Tp, typename _Proj = identity>
+#endif
requires indirect_binary_predicate<ranges::equal_to,
projected<iterator_t<_Range>, _Proj>, const _Tp*>
constexpr bool
@@ -3525,7 +3695,13 @@ namespace ranges
struct __find_last_fn
{
+#if __glibcxx_default_template_type_for_algorithm_values
+ template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Proj = identity,
+ typename _Tp = projected_value_t<_Iter, _Proj>>
+#else
template<forward_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Tp, typename _Proj = identity>
+#endif
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 +3732,12 @@ namespace ranges
}
}
+#if __glibcxx_default_template_type_for_algorithm_values
+ template<forward_range _Range, typename _Proj = identity,
+ typename _Tp = projected_value_t<iterator_t<_Range>, _Proj>>
+#else
template<forward_range _Range, typename _Tp, typename _Proj = identity>
+#endif
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,8 +3911,11 @@ namespace ranges
return _Ret{std::move(__first), std::move(__accum)};
}
- template<input_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Tp,
- __detail::__indirectly_binary_left_foldable<_Tp, _Iter> _Fp>
+ template<input_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Tp
+#if __glibcxx_default_template_type_for_algorithm_values
+ = iter_value_t<_Iter>
+#endif
+ , __detail::__indirectly_binary_left_foldable<_Tp, _Iter> _Fp>
constexpr auto
operator()(_Iter __first, _Sent __last, _Tp __init, _Fp __f) const
{
@@ -3740,8 +3924,11 @@ namespace ranges
std::move(__init), std::move(__f));
}
- template<input_range _Range, typename _Tp,
- __detail::__indirectly_binary_left_foldable<_Tp, iterator_t<_Range>> _Fp>
+ template<input_range _Range, typename _Tp
+#if __glibcxx_default_template_type_for_algorithm_values
+ = range_value_t<_Range>
+#endif
+ , __detail::__indirectly_binary_left_foldable<_Tp, iterator_t<_Range>> _Fp>
constexpr auto
operator()(_Range&& __r, _Tp __init, _Fp __f) const
{
@@ -3755,8 +3942,11 @@ namespace ranges
struct __fold_left_fn
{
- template<input_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Tp,
- __detail::__indirectly_binary_left_foldable<_Tp, _Iter> _Fp>
+ template<input_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Tp
+#if __glibcxx_default_template_type_for_algorithm_values
+ = iter_value_t<_Iter>
+#endif
+ , __detail::__indirectly_binary_left_foldable<_Tp, _Iter> _Fp>
constexpr auto
operator()(_Iter __first, _Sent __last, _Tp __init, _Fp __f) const
{
@@ -3764,8 +3954,11 @@ namespace ranges
std::move(__init), std::move(__f)).value;
}
- template<input_range _Range, typename _Tp,
- __detail::__indirectly_binary_left_foldable<_Tp, iterator_t<_Range>> _Fp>
+ template<input_range _Range, typename _Tp
+#if __glibcxx_default_template_type_for_algorithm_values
+ = range_value_t<_Range>
+#endif
+ , __detail::__indirectly_binary_left_foldable<_Tp, iterator_t<_Range>> _Fp>
constexpr auto
operator()(_Range&& __r, _Tp __init, _Fp __f) const
{ return (*this)(ranges::begin(__r), ranges::end(__r), std::move(__init), std::move(__f)); }
@@ -3842,8 +4035,11 @@ namespace ranges
struct __fold_right_fn
{
- template<bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Tp,
- __detail::__indirectly_binary_right_foldable<_Tp, _Iter> _Fp>
+ template<bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Tp
+#if __glibcxx_default_template_type_for_algorithm_values
+ = iter_value_t<_Iter>
+#endif
+ , __detail::__indirectly_binary_right_foldable<_Tp, _Iter> _Fp>
constexpr auto
operator()(_Iter __first, _Sent __last, _Tp __init, _Fp __f) const
{
@@ -3859,8 +4055,11 @@ namespace ranges
return __accum;
}
- template<bidirectional_range _Range, typename _Tp,
- __detail::__indirectly_binary_right_foldable<_Tp, iterator_t<_Range>> _Fp>
+ template<bidirectional_range _Range, typename _Tp
+#if __glibcxx_default_template_type_for_algorithm_values
+ = range_value_t<_Range>
+#endif
+ , __detail::__indirectly_binary_right_foldable<_Tp, iterator_t<_Range>> _Fp>
constexpr auto
operator()(_Range&& __r, _Tp __init, _Fp __f) const
{ return (*this)(ranges::begin(__r), ranges::end(__r), std::move(__init), std::move(__f)); }
@@ -40,6 +40,9 @@
#include <bits/cpp_type_traits.h> // __is_byte
#include <bits/stl_algobase.h> // __memcmp
+#define __glibcxx_want_default_template_type_for_algorithm_values
+#include <bits/version.h>
+
#if __cpp_lib_concepts
namespace std _GLIBCXX_VISIBILITY(default)
{
@@ -536,7 +539,12 @@ namespace ranges
struct __fill_n_fn
{
+#if __glibcxx_default_template_type_for_algorithm_values
+ template<typename _Out, typename _Tp = iter_value_t<_Out>>
+ requires output_iterator<_Out, const _Tp&>
+#else
template<typename _Tp, output_iterator<const _Tp&> _Out>
+#endif
constexpr _Out
operator()(_Out __first, iter_difference_t<_Out> __n,
const _Tp& __value) const
@@ -581,8 +589,15 @@ namespace ranges
struct __fill_fn
{
+#if __glibcxx_default_template_type_for_algorithm_values
+ template<typename _Out,
+ sentinel_for<_Out> _Sent,
+ typename _Tp = iter_value_t<_Out>>
+ requires output_iterator<_Out, const _Tp&>
+#else
template<typename _Tp,
output_iterator<const _Tp&> _Out, sentinel_for<_Out> _Sent>
+#endif
constexpr _Out
operator()(_Out __first, _Sent __last, const _Tp& __value) const
{
@@ -608,7 +623,12 @@ namespace ranges
}
}
+#if __glibcxx_default_template_type_for_algorithm_values
+ template<typename _Range, typename _Tp = range_value_t<_Range>>
+ requires output_range<_Range, const _Tp&>
+#else
template<typename _Tp, output_range<const _Tp&> _Range>
+#endif
constexpr borrowed_iterator_t<_Range>
operator()(_Range&& __r, const _Tp& __value) const
{
@@ -36,6 +36,9 @@
# include <bits/invoke.h>
# include <bits/cpp_type_traits.h> // __can_use_memchr_for_find
+#define __glibcxx_want_default_template_type_for_algorithm_values
+#include <bits/version.h>
+
#ifdef __glibcxx_ranges
namespace std _GLIBCXX_VISIBILITY(default)
{
@@ -487,8 +490,13 @@ namespace ranges
{
struct __find_fn
{
+#if __glibcxx_default_template_type_for_algorithm_values
+ template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
+ typename _Proj = identity, typename _Tp = projected_value_t<_Iter, _Proj>>
+#else
template<input_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Tp,
typename _Proj = identity>
+#endif
requires indirect_binary_predicate<ranges::equal_to,
projected<_Iter, _Proj>, const _Tp*>
constexpr _Iter
@@ -521,7 +529,12 @@ namespace ranges
return __first;
}
+#if __glibcxx_default_template_type_for_algorithm_values
+ template<input_range _Range, typename _Proj = identity,
+ typename _Tp = projected_value_t<iterator_t<_Range>, _Proj>>
+#else
template<input_range _Range, typename _Tp, typename _Proj = identity>
+#endif
requires indirect_binary_predicate<ranges::equal_to,
projected<iterator_t<_Range>, _Proj>,
const _Tp*>
new file mode 100644
@@ -0,0 +1,45 @@
+// Helpers for STL algorithms' default template argument -*- C++ -*-
+
+// Copyright (C) 2007-2024 Free Software Foundation, Inc.
+//
+// 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/>.
+
+/** @file bits/stl_algorithm_default.h
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{algorithm}
+ */
+
+#ifndef _GLIBCXX_STL_ALGORITHM_DEFAULT_H
+#define _GLIBCXX_STL_ALGORITHM_DEFAULT_H 1
+
+#include <bits/stl_iterator_base_types.h>
+
+#define __glibcxx_want_default_template_type_for_algorithm_values
+#include <bits/version.h>
+
+#if __glibcxx_default_template_type_for_algorithm_values // C++ >= 26
+#define _GLIBCXX26_DEFAULT_TEMPLATE_TYPE_FOR_ALGORITHM_VALUE(_Iterator) \
+ = typename iterator_traits<_Iterator>::value_type
+#else
+#define _GLIBCXX26_DEFAULT_TEMPLATE_TYPE_FOR_ALGORITHM_VALUE(_It)
+#endif
+
+#endif
@@ -1828,6 +1828,14 @@ ftms = {
};
};
+ftms = {
+ name = default_template_type_for_algorithm_values;
+ values = {
+ v = 202403;
+ cxxmin = 26;
+ };
+};
+
// Standard test specifications.
stds[97] = ">= 199711L";
stds[03] = ">= 199711L";
@@ -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_default_template_type_for_algorithm_values)
+# if (__cplusplus > 202302L)
+# define __glibcxx_default_template_type_for_algorithm_values 202403L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_default_template_type_for_algorithm_values)
+# define __cpp_lib_default_template_type_for_algorithm_values 202403L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_default_template_type_for_algorithm_values) && defined(__glibcxx_want_default_template_type_for_algorithm_values) */
+#undef __glibcxx_want_default_template_type_for_algorithm_values
+
#undef __glibcxx_want_all
@@ -11,6 +11,7 @@
#define _PSTL_GLUE_ALGORITHM_DEFS_H
#include <bits/stl_pair.h>
+#include <bits/stl_algorithm_default.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_DEFAULT_TEMPLATE_TYPE_FOR_ALGORITHM_VALUE(_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_DEFAULT_TEMPLATE_TYPE_FOR_ALGORITHM_VALUE(_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_DEFAULT_TEMPLATE_TYPE_FOR_ALGORITHM_VALUE(_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_DEFAULT_TEMPLATE_TYPE_FOR_ALGORITHM_VALUE(_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_DEFAULT_TEMPLATE_TYPE_FOR_ALGORITHM_VALUE(_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_DEFAULT_TEMPLATE_TYPE_FOR_ALGORITHM_VALUE(_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_DEFAULT_TEMPLATE_TYPE_FOR_ALGORITHM_VALUE(_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_DEFAULT_TEMPLATE_TYPE_FOR_ALGORITHM_VALUE(_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_DEFAULT_TEMPLATE_TYPE_FOR_ALGORITHM_VALUE(_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_DEFAULT_TEMPLATE_TYPE_FOR_ALGORITHM_VALUE(_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_DEFAULT_TEMPLATE_TYPE_FOR_ALGORITHM_VALUE(_ForwardIterator)>
__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator>
remove(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, const _Tp& __value);
@@ -65,6 +65,7 @@
#define __glibcxx_want_clamp
#define __glibcxx_want_constexpr_algorithms
+#define __glibcxx_want_default_template_type_for_algorithm_values
#define __glibcxx_want_freestanding_algorithm
#define __glibcxx_want_parallel_algorithm
#define __glibcxx_want_ranges
@@ -68,6 +68,7 @@
#include <bits/range_access.h>
#include <bits/deque.tcc>
+#define __glibcxx_want_default_template_type_for_algorithm_values
#define __glibcxx_want_erase_if
#define __glibcxx_want_nonmember_container_access
#include <bits/version.h>
@@ -115,7 +116,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return 0;
}
- template<typename _Tp, typename _Alloc, typename _Up>
+ template<typename _Tp, typename _Alloc, typename _Up
+#if __glibcxx_default_template_type_for_algorithm_values // C++ >= 26
+ = _Tp
+#endif
+ >
inline typename deque<_Tp, _Alloc>::size_type
erase(deque<_Tp, _Alloc>& __cont, const _Up& __value)
{
@@ -45,6 +45,7 @@
# include <debug/forward_list>
#endif
+#define __glibcxx_want_default_template_type_for_algorithm_values
#define __glibcxx_want_erase_if
#define __glibcxx_want_incomplete_container_elements
#define __glibcxx_want_list_remove_return_type
@@ -74,7 +75,11 @@ _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
+#if __glibcxx_default_template_type_for_algorithm_values // C++ >= 26
+ = _Tp
+#endif
+ >
inline typename forward_list<_Tp, _Alloc>::size_type
erase(forward_list<_Tp, _Alloc>& __cont, const _Up& __value)
{
@@ -69,6 +69,7 @@
# include <debug/list>
#endif
+#define __glibcxx_want_default_template_type_for_algorithm_values
#define __glibcxx_want_erase_if
#define __glibcxx_want_incomplete_container_elements
#define __glibcxx_want_list_remove_return_type
@@ -98,7 +99,11 @@ _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
+#if __glibcxx_default_template_type_for_algorithm_values // C++ >= 26
+ = _Tp
+#endif
+ >
inline typename list<_Tp, _Alloc>::size_type
erase(list<_Tp, _Alloc>& __cont, const _Up& __value)
{
@@ -51,6 +51,7 @@
#include <bits/ranges_util.h>
#include <bits/refwrap.h>
+#define __glibcxx_want_default_template_type_for_algorithm_values
#define __glibcxx_want_ranges
#define __glibcxx_want_ranges_as_const
#define __glibcxx_want_ranges_as_rvalue
@@ -56,6 +56,7 @@
#define __glibcxx_want_constexpr_char_traits
#define __glibcxx_want_constexpr_string
+#define __glibcxx_want_default_template_type_for_algorithm_values
#define __glibcxx_want_erase_if
#define __glibcxx_want_nonmember_container_access
#define __glibcxx_want_string_resize_and_overwrite
@@ -104,7 +105,11 @@ _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
+#if __glibcxx_default_template_type_for_algorithm_values // C++ >= 26
+ = _CharT
+#endif
+ >
_GLIBCXX20_CONSTEXPR
inline typename basic_string<_CharT, _Traits, _Alloc>::size_type
erase(basic_string<_CharT, _Traits, _Alloc>& __cont, const _Up& __value)
@@ -77,6 +77,7 @@
#endif
#define __glibcxx_want_constexpr_vector
+#define __glibcxx_want_default_template_type_for_algorithm_values
#define __glibcxx_want_erase_if
#define __glibcxx_want_incomplete_container_elements
#define __glibcxx_want_nonmember_container_access
@@ -128,7 +129,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return 0;
}
- template<typename _Tp, typename _Alloc, typename _Up>
+ template<typename _Tp, typename _Alloc, typename _Up
+#if __glibcxx_default_template_type_for_algorithm_values // C++ >= 26
+ = _Tp
+#endif
+ >
_GLIBCXX20_CONSTEXPR
inline typename vector<_Tp, _Alloc>::size_type
erase(vector<_Tp, _Alloc>& __cont, const _Up& __value)
new file mode 100644
@@ -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_default_template_type_for_algorithm_values)
+#error "Feature test macro for default template type for algorithms' values is missing"
+#elif __cpp_lib_default_template_type_for_algorithm_values < 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'});
+}
new file mode 100644
@@ -0,0 +1,142 @@
+// { dg-do compile { target c++26 } }
+
+#include <algorithm>
+
+#if !defined(__cpp_lib_default_template_type_for_algorithm_values)
+#error "Feature test macro for default template type for algorithms' values is missing"
+#elif __cpp_lib_default_template_type_for_algorithm_values < 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