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.

Thanks,

--
Giuseppe D'Angelo
From 9f1a84548ecea9859c1f8d70c533e4e5a0701870 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, 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.dang...@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

diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 422a0f4bd0a..9da3f930dba 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -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 \
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
index 9fd4ab4848c..2f39f484ab6 100644
--- a/libstdc++-v3/include/Makefile.in
+++ b/libstdc++-v3/include/Makefile.in
@@ -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 \
diff --git a/libstdc++-v3/include/bits/algorithmfwd.h b/libstdc++-v3/include/bits/algorithmfwd.h
index 34bf9921f43..2b93f35985f 100644
--- a/libstdc++-v3/include/bits/algorithmfwd.h
+++ b/libstdc++-v3/include/bits/algorithmfwd.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
diff --git a/libstdc++-v3/include/bits/iterator_concepts.h b/libstdc++-v3/include/bits/iterator_concepts.h
index ce0b8a10f88..47e19514465 100644
--- a/libstdc++-v3/include/bits/iterator_concepts.h
+++ b/libstdc++-v3/include/bits/iterator_concepts.h
@@ -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`
diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h
index d258be0b93f..90d0932656e 100644
--- a/libstdc++-v3/include/bits/ranges_algo.h
+++ b/libstdc++-v3/include/bits/ranges_algo.h
@@ -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)); }
diff --git a/libstdc++-v3/include/bits/ranges_algobase.h b/libstdc++-v3/include/bits/ranges_algobase.h
index fd35b8ba14c..2b7eb74029f 100644
--- a/libstdc++-v3/include/bits/ranges_algobase.h
+++ b/libstdc++-v3/include/bits/ranges_algobase.h
@@ -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
       {
diff --git a/libstdc++-v3/include/bits/ranges_util.h b/libstdc++-v3/include/bits/ranges_util.h
index e6d96073e87..062f272152e 100644
--- a/libstdc++-v3/include/bits/ranges_util.h
+++ b/libstdc++-v3/include/bits/ranges_util.h
@@ -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*>
diff --git a/libstdc++-v3/include/bits/stl_algorithm_default.h b/libstdc++-v3/include/bits/stl_algorithm_default.h
new file mode 100644
index 00000000000..09e7be1b335
--- /dev/null
+++ b/libstdc++-v3/include/bits/stl_algorithm_default.h
@@ -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
diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def
index 47335bfa6dd..1979751e7ba 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -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";
diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h
index defe54ac1f2..497727e995c 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_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
diff --git a/libstdc++-v3/include/pstl/glue_algorithm_defs.h b/libstdc++-v3/include/pstl/glue_algorithm_defs.h
index cef78e22e31..8c07c25cd92 100644
--- a/libstdc++-v3/include/pstl/glue_algorithm_defs.h
+++ b/libstdc++-v3/include/pstl/glue_algorithm_defs.h
@@ -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);
 
diff --git a/libstdc++-v3/include/std/algorithm b/libstdc++-v3/include/std/algorithm
index 163e6b5dca7..359617b8672 100644
--- a/libstdc++-v3/include/std/algorithm
+++ b/libstdc++-v3/include/std/algorithm
@@ -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
diff --git a/libstdc++-v3/include/std/deque b/libstdc++-v3/include/std/deque
index 0bf8309c19a..05acb8a0d54 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_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)
     {
diff --git a/libstdc++-v3/include/std/forward_list b/libstdc++-v3/include/std/forward_list
index 5ac74360808..4419d0e5aec 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_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)
     {
diff --git a/libstdc++-v3/include/std/list b/libstdc++-v3/include/std/list
index fce4e3d925b..9b5e9957786 100644
--- a/libstdc++-v3/include/std/list
+++ b/libstdc++-v3/include/std/list
@@ -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)
     {
diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
index b7c7aa36ddc..8dca469dd2c 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_default_template_type_for_algorithm_values
 #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..54c751038cd 100644
--- a/libstdc++-v3/include/std/string
+++ b/libstdc++-v3/include/std/string
@@ -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)
diff --git a/libstdc++-v3/include/std/vector b/libstdc++-v3/include/std/vector
index a1f7ef86824..e5262e82b89 100644
--- a/libstdc++-v3/include/std/vector
+++ b/libstdc++-v3/include/std/vector
@@ -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)
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..070e0deea4c
--- /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_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'});
+}
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..6086d441168
--- /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_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

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature

Reply via email to