https://gcc.gnu.org/g:dc47add79261679747302293e1a5e49ba96276b1

commit r15-3769-gdc47add79261679747302293e1a5e49ba96276b1
Author: Jonathan Wakely <jwak...@redhat.com>
Date:   Fri Sep 13 10:18:46 2024 +0100

    libstdc++: add default template parameters to algorithms
    
    This implements P2248R8 + P3217R0, both approved for C++26.
    The changes are mostly mechanical; the struggle is to keep readability
    with the pre-P2248 signatures.
    
    * For containers, "classic STL" algorithms and their parallel versions,
      introduce a macro and amend their declarations/definitions with it.
      The macro either expands to the defaulted parameter or to nothing
      in pre-C++26 modes.
    
    * For range algorithms, we need to reorder their template parameters.
      I've done so unconditionally, because users cannot rely on template
      parameters of algorithms (this is explicitly authorized by
      [algorithms.requirements]/15). The defaults are then hidden behind
      another macro.
    
    libstdc++-v3/ChangeLog:
    
            * include/bits/iterator_concepts.h: Add projected_value_t.
            * include/bits/algorithmfwd.h: Add the default template
            parameter to the relevant forward declarations.
            * include/pstl/glue_algorithm_defs.h: Likewise.
            * include/bits/ranges_algo.h: Add the default template
            parameter to range-based algorithms.
            * include/bits/ranges_algobase.h: Likewise.
            * include/bits/ranges_util.h: Likewise.
            * include/bits/ranges_base.h: Add helper macros.
            * include/bits/stl_iterator_base_types.h: Add helper macro.
            * include/bits/version.def: Add the new feature-testing macro.
            * include/bits/version.h: Regenerate.
            * include/std/algorithm: Pull the feature-testing macro.
            * include/std/ranges: Likewise.
            * include/std/deque: Pull the feature-testing macro, add
            the default for std::erase.
            * include/std/forward_list: Likewise.
            * include/std/list: Likewise.
            * include/std/string: Likewise.
            * include/std/vector: Likewise.
            * testsuite/23_containers/default_template_value.cc: New test.
            * testsuite/25_algorithms/default_template_value.cc: New test.
    
    Signed-off-by: Giuseppe D'Angelo <giuseppe.dang...@kdab.com>
    Co-authored-by: Jonathan Wakely <jwak...@redhat.com>

Diff:
---
 libstdc++-v3/include/bits/algorithmfwd.h           |  48 ++++---
 libstdc++-v3/include/bits/iterator_concepts.h      |   7 +
 libstdc++-v3/include/bits/ranges_algo.h            | 135 ++++++++++++++------
 libstdc++-v3/include/bits/ranges_algobase.h        |  14 +-
 libstdc++-v3/include/bits/ranges_base.h            |   6 +
 libstdc++-v3/include/bits/ranges_util.h            |   9 +-
 .../include/bits/stl_iterator_base_types.h         |   9 ++
 libstdc++-v3/include/bits/version.def              |   8 ++
 libstdc++-v3/include/bits/version.h                |  10 ++
 libstdc++-v3/include/pstl/glue_algorithm_defs.h    |  23 ++--
 libstdc++-v3/include/std/algorithm                 |   1 +
 libstdc++-v3/include/std/deque                     |   4 +-
 libstdc++-v3/include/std/forward_list              |   4 +-
 libstdc++-v3/include/std/list                      |   4 +-
 libstdc++-v3/include/std/ranges                    |   1 +
 libstdc++-v3/include/std/string                    |   4 +-
 libstdc++-v3/include/std/vector                    |   4 +-
 .../23_containers/default_template_value.cc        |  40 ++++++
 .../25_algorithms/default_template_value.cc        | 142 +++++++++++++++++++++
 19 files changed, 392 insertions(+), 81 deletions(-)

diff --git a/libstdc++-v3/include/bits/algorithmfwd.h 
b/libstdc++-v3/include/bits/algorithmfwd.h
index 7f1f15970abe..df14864d210e 100644
--- a/libstdc++-v3/include/bits/algorithmfwd.h
+++ b/libstdc++-v3/include/bits/algorithmfwd.h
@@ -206,12 +206,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     any_of(_IIter, _IIter, _Predicate);
 #endif
 
-  template<typename _FIter, typename _Tp>
+  template<typename _FIter, typename _Tp _GLIBCXX26_ALGO_DEF_VAL_T(_FIter)>
     _GLIBCXX20_CONSTEXPR
     bool
     binary_search(_FIter, _FIter, const _Tp&);
 
-  template<typename _FIter, typename _Tp, typename _Compare>
+  template<typename _FIter, typename _Tp _GLIBCXX26_ALGO_DEF_VAL_T(_FIter),
+          typename _Compare>
     _GLIBCXX20_CONSTEXPR
     bool
     binary_search(_FIter, _FIter, const _Tp&, _Compare);
@@ -253,22 +254,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // count
   // count_if
 
-  template<typename _FIter, typename _Tp>
+  template<typename _FIter, typename _Tp _GLIBCXX26_ALGO_DEF_VAL_T(_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_ALGO_DEF_VAL_T(_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_ALGO_DEF_VAL_T(_FIter)>
     _GLIBCXX20_CONSTEXPR
     void
     fill(_FIter, _FIter, const _Tp&);
 
-  template<typename _OIter, typename _Size, typename _Tp>
+  template<typename _OIter, typename _Size,
+          typename _Tp _GLIBCXX26_ALGO_DEF_VAL_T(_OIter)>
     _GLIBCXX20_CONSTEXPR
     _OIter
     fill_n(_OIter, _Size, const _Tp&);
@@ -380,12 +383,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     void
     iter_swap(_FIter1, _FIter2);
 
-  template<typename _FIter, typename _Tp>
+  template<typename _FIter, typename _Tp _GLIBCXX26_ALGO_DEF_VAL_T(_FIter)>
     _GLIBCXX20_CONSTEXPR
     _FIter
     lower_bound(_FIter, _FIter, const _Tp&);
 
-  template<typename _FIter, typename _Tp, typename _Compare>
+  template<typename _FIter, typename _Tp _GLIBCXX26_ALGO_DEF_VAL_T(_FIter),
+          typename _Compare>
     _GLIBCXX20_CONSTEXPR
     _FIter
     lower_bound(_FIter, _FIter, const _Tp&, _Compare);
@@ -556,7 +560,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   // random_shuffle
 
-  template<typename _FIter, typename _Tp>
+  template<typename _FIter, typename _Tp _GLIBCXX26_ALGO_DEF_VAL_T(_FIter)>
     _GLIBCXX20_CONSTEXPR
     _FIter
     remove(_FIter, _FIter, const _Tp&);
@@ -566,7 +570,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_ALGO_DEF_VAL_T(_IIter)>
     _GLIBCXX20_CONSTEXPR
     _OIter
     remove_copy(_IIter, _IIter, _OIter, const _Tp&);
@@ -583,7 +588,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_ALGO_DEF_VAL_T(_OIter)>
     _GLIBCXX20_CONSTEXPR
     _OIter
     replace_copy_if(_Iter, _Iter, _OIter, _Predicate, const _Tp&);
@@ -676,12 +682,13 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
 
   // unique_copy
 
-  template<typename _FIter, typename _Tp>
+  template<typename _FIter, typename _Tp _GLIBCXX26_ALGO_DEF_VAL_T(_FIter)>
     _GLIBCXX20_CONSTEXPR
     _FIter
     upper_bound(_FIter, _FIter, const _Tp&);
 
-  template<typename _FIter, typename _Tp, typename _Compare>
+  template<typename _FIter, typename _Tp _GLIBCXX26_ALGO_DEF_VAL_T(_FIter),
+          typename _Compare>
     _GLIBCXX20_CONSTEXPR
     _FIter
     upper_bound(_FIter, _FIter, const _Tp&, _Compare);
@@ -698,7 +705,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
     _FIter
     adjacent_find(_FIter, _FIter, _BinaryPredicate);
 
-  template<typename _IIter, typename _Tp>
+  template<typename _IIter, typename _Tp _GLIBCXX26_ALGO_DEF_VAL_T(_IIter)>
     _GLIBCXX20_CONSTEXPR
     typename iterator_traits<_IIter>::difference_type
     count(_IIter, _IIter, const _Tp&);
@@ -718,7 +725,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
     bool
     equal(_IIter1, _IIter1, _IIter2, _BinaryPredicate);
 
-  template<typename _IIter, typename _Tp>
+  template<typename _IIter, typename _Tp _GLIBCXX26_ALGO_DEF_VAL_T(_IIter)>
     _GLIBCXX20_CONSTEXPR
     _IIter
     find(_IIter, _IIter, const _Tp&);
@@ -846,12 +853,13 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
 #endif
 #endif // HOSTED
 
-  template<typename _FIter, typename _Tp>
+  template<typename _FIter, typename _Tp _GLIBCXX26_ALGO_DEF_VAL_T(_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_ALGO_DEF_VAL_T(_FIter)>
     _GLIBCXX20_CONSTEXPR
     void
     replace_if(_FIter, _FIter, _Predicate, const _Tp&);
@@ -866,12 +874,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_ALGO_DEF_VAL_T(_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_ALGO_DEF_VAL_T(_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 4ac6e6bfbe7a..d96573f4213b 100644
--- a/libstdc++-v3/include/bits/iterator_concepts.h
+++ b/libstdc++-v3/include/bits/iterator_concepts.h
@@ -829,6 +829,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       using type = invoke_result_t<_Proj&, __indirect_value_t<_Iter>>;
     };
 
+#if __glibcxx_algorithm_default_value_type // C++ >= 26
+  template<indirectly_readable _Iter,
+          indirectly_regular_unary_invocable<_Iter> _Proj>
+    using projected_value_t
+       = remove_cvref_t<invoke_result_t<_Proj&, iter_value_t<_Iter>&>>;
+#endif
+
   // [alg.req], common algorithm requirements
 
   /// [alg.req.ind.move], concept `indirectly_movable`
diff --git a/libstdc++-v3/include/bits/ranges_algo.h 
b/libstdc++-v3/include/bits/ranges_algo.h
index d258be0b93f3..bae36637b3e3 100644
--- a/libstdc++-v3/include/bits/ranges_algo.h
+++ b/libstdc++-v3/include/bits/ranges_algo.h
@@ -281,7 +281,8 @@ namespace ranges
   struct __count_fn
   {
     template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
-            typename _Tp, typename _Proj = identity>
+            typename _Proj = identity,
+            typename _Tp _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_Iter, _Proj)>
       requires indirect_binary_predicate<ranges::equal_to,
                                         projected<_Iter, _Proj>,
                                         const _Tp*>
@@ -296,7 +297,9 @@ namespace ranges
        return __n;
       }
 
-    template<input_range _Range, typename _Tp, typename _Proj = identity>
+    template<input_range _Range, typename _Proj = identity,
+            typename _Tp
+              _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(iterator_t<_Range>, _Proj)>
       requires indirect_binary_predicate<ranges::equal_to,
                                         projected<iterator_t<_Range>, _Proj>,
                                         const _Tp*>
@@ -344,8 +347,9 @@ namespace ranges
 
   struct __search_n_fn
   {
-    template<forward_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Tp,
-            typename _Pred = ranges::equal_to, typename _Proj = identity>
+    template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
+            typename _Pred = ranges::equal_to, typename _Proj = identity,
+            typename _Tp _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_Iter, _Proj)>
       requires indirectly_comparable<_Iter, const _Tp*, _Pred, _Proj>
       constexpr subrange<_Iter>
       operator()(_Iter __first, _Sent __last, iter_difference_t<_Iter> __count,
@@ -416,8 +420,10 @@ namespace ranges
          }
       }
 
-    template<forward_range _Range, typename _Tp,
-            typename _Pred = ranges::equal_to, typename _Proj = identity>
+    template<forward_range _Range,
+            typename _Pred = ranges::equal_to, typename _Proj = identity,
+            typename _Tp
+              _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(iterator_t<_Range>, _Proj)>
       requires indirectly_comparable<iterator_t<_Range>, const _Tp*,
                                     _Pred, _Proj>
       constexpr borrowed_subrange_t<_Range>
@@ -774,7 +780,9 @@ namespace ranges
   struct __replace_fn
   {
     template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
-            typename _Tp1, typename _Tp2, typename _Proj = identity>
+            typename _Proj = identity,
+            typename _Tp1 _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_Iter, _Proj),
+            typename _Tp2 _GLIBCXX26_DEF_VAL_T(_Tp1)>
       requires indirectly_writable<_Iter, const _Tp2&>
        && indirect_binary_predicate<ranges::equal_to, projected<_Iter, _Proj>,
                                     const _Tp1*>
@@ -789,8 +797,10 @@ namespace ranges
        return __first;
       }
 
-    template<input_range _Range,
-            typename _Tp1, typename _Tp2, typename _Proj = identity>
+    template<input_range _Range, typename _Proj = identity,
+            typename _Tp1
+              _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(iterator_t<_Range>, _Proj),
+            typename _Tp2 _GLIBCXX26_DEF_VAL_T(_Tp1)>
       requires indirectly_writable<iterator_t<_Range>, const _Tp2&>
        && indirect_binary_predicate<ranges::equal_to,
                                     projected<iterator_t<_Range>, _Proj>,
@@ -810,7 +820,8 @@ namespace ranges
   struct __replace_if_fn
   {
     template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
-            typename _Tp, typename _Proj = identity,
+            typename _Proj = identity,
+            typename _Tp _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_Iter, _Proj),
             indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
       requires indirectly_writable<_Iter, const _Tp&>
       constexpr _Iter
@@ -823,7 +834,9 @@ namespace ranges
        return std::move(__first);
       }
 
-    template<input_range _Range, typename _Tp, typename _Proj = identity,
+    template<input_range _Range, typename _Proj = identity,
+            typename _Tp
+              _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(iterator_t<_Range>, _Proj),
             indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
               _Pred>
       requires indirectly_writable<iterator_t<_Range>, const _Tp&>
@@ -844,11 +857,13 @@ namespace ranges
   struct __replace_copy_fn
   {
     template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
-            typename _Tp1, typename _Tp2, output_iterator<const _Tp2&> _Out,
-            typename _Proj = identity>
+            typename _Out, typename _Proj = identity,
+            typename _Tp1 _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_Iter, _Proj),
+            typename _Tp2 _GLIBCXX26_DEF_VAL_T(iter_value_t<_Out>)>
       requires indirectly_copyable<_Iter, _Out>
        && indirect_binary_predicate<ranges::equal_to,
                                     projected<_Iter, _Proj>, const _Tp1*>
+       && output_iterator<_Out, const _Tp2&>
       constexpr replace_copy_result<_Iter, _Out>
       operator()(_Iter __first, _Sent __last, _Out __result,
                 const _Tp1& __old_value, const _Tp2& __new_value,
@@ -862,12 +877,16 @@ namespace ranges
        return {std::move(__first), std::move(__result)};
       }
 
-    template<input_range _Range, typename _Tp1, typename _Tp2,
-            output_iterator<const _Tp2&> _Out, typename _Proj = identity>
+    template<input_range _Range, typename _Out,
+            typename _Proj = identity,
+            typename _Tp1
+              _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(iterator_t<_Range>, _Proj),
+            typename _Tp2 _GLIBCXX26_DEF_VAL_T(iter_value_t<_Out>)>
       requires indirectly_copyable<iterator_t<_Range>, _Out>
        && indirect_binary_predicate<ranges::equal_to,
                                     projected<iterator_t<_Range>, _Proj>,
                                     const _Tp1*>
+       && output_iterator<_Out, const _Tp2&>
       constexpr replace_copy_result<borrowed_iterator_t<_Range>, _Out>
       operator()(_Range&& __r, _Out __result,
                 const _Tp1& __old_value, const _Tp2& __new_value,
@@ -887,10 +906,12 @@ namespace ranges
   struct __replace_copy_if_fn
   {
     template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
-            typename _Tp, output_iterator<const _Tp&> _Out,
+            typename _Out,
+            typename _Tp _GLIBCXX26_DEF_VAL_T(iter_value_t<_Out>),
             typename _Proj = identity,
             indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
       requires indirectly_copyable<_Iter, _Out>
+       && output_iterator<_Out, const _Tp&>
       constexpr replace_copy_if_result<_Iter, _Out>
       operator()(_Iter __first, _Sent __last, _Out __result,
                 _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) const
@@ -904,11 +925,13 @@ namespace ranges
       }
 
     template<input_range _Range,
-            typename _Tp, output_iterator<const _Tp&> _Out,
+            typename _Out,
+            typename _Tp _GLIBCXX26_DEF_VAL_T(iter_value_t<_Out>),
             typename _Proj = identity,
             indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
               _Pred>
       requires indirectly_copyable<iterator_t<_Range>, _Out>
+       && output_iterator<_Out, const _Tp&>
       constexpr replace_copy_if_result<borrowed_iterator_t<_Range>, _Out>
       operator()(_Range&& __r, _Out __result,
                 _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) const
@@ -1004,7 +1027,8 @@ namespace ranges
   struct __remove_fn
   {
     template<permutable _Iter, sentinel_for<_Iter> _Sent,
-            typename _Tp, typename _Proj = identity>
+            typename _Proj = identity,
+            typename _Tp _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_Iter, _Proj)>
       requires indirect_binary_predicate<ranges::equal_to,
                                         projected<_Iter, _Proj>,
                                         const _Tp*>
@@ -1019,7 +1043,9 @@ namespace ranges
                                 std::move(__pred), std::move(__proj));
       }
 
-    template<forward_range _Range, typename _Tp, typename _Proj = identity>
+    template<forward_range _Range, typename _Proj = identity,
+            typename _Tp
+              _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(iterator_t<_Range>, _Proj)>
       requires permutable<iterator_t<_Range>>
        && indirect_binary_predicate<ranges::equal_to,
                                     projected<iterator_t<_Range>, _Proj>,
@@ -1079,7 +1105,8 @@ namespace ranges
   struct __remove_copy_fn
   {
     template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
-            weakly_incrementable _Out, typename _Tp, typename _Proj = identity>
+            weakly_incrementable _Out, typename _Proj = identity,
+            typename _Tp _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_Iter, _Proj)>
       requires indirectly_copyable<_Iter, _Out>
        && indirect_binary_predicate<ranges::equal_to,
                                     projected<_Iter, _Proj>,
@@ -1098,7 +1125,9 @@ namespace ranges
       }
 
     template<input_range _Range, weakly_incrementable _Out,
-            typename _Tp, typename _Proj = identity>
+            typename _Proj = identity,
+            typename _Tp
+              _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(iterator_t<_Range>, _Proj)>
       requires indirectly_copyable<iterator_t<_Range>, _Out>
        && indirect_binary_predicate<ranges::equal_to,
                                     projected<iterator_t<_Range>, _Proj>,
@@ -2047,7 +2076,8 @@ namespace ranges
   struct __lower_bound_fn
   {
     template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
-            typename _Tp, typename _Proj = identity,
+            typename _Proj = identity,
+            typename _Tp _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_Iter, _Proj),
             indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>>
               _Comp = ranges::less>
       constexpr _Iter
@@ -2073,7 +2103,10 @@ namespace ranges
        return __first;
       }
 
-    template<forward_range _Range, typename _Tp, typename _Proj = identity,
+    template<forward_range _Range,
+            typename _Proj = identity,
+            typename _Tp
+              _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(iterator_t<_Range>, _Proj),
             indirect_strict_weak_order<const _Tp*,
                                        projected<iterator_t<_Range>, _Proj>>
               _Comp = ranges::less>
@@ -2091,7 +2124,8 @@ namespace ranges
   struct __upper_bound_fn
   {
     template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
-            typename _Tp, typename _Proj = identity,
+            typename _Proj = identity,
+            typename _Tp _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_Iter, _Proj),
             indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>>
               _Comp = ranges::less>
       constexpr _Iter
@@ -2117,7 +2151,10 @@ namespace ranges
        return __first;
       }
 
-    template<forward_range _Range, typename _Tp, typename _Proj = identity,
+    template<forward_range _Range,
+            typename _Proj = identity,
+            typename _Tp
+              _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(iterator_t<_Range>, _Proj),
             indirect_strict_weak_order<const _Tp*,
                                        projected<iterator_t<_Range>, _Proj>>
               _Comp = ranges::less>
@@ -2135,7 +2172,8 @@ namespace ranges
   struct __equal_range_fn
   {
     template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
-            typename _Tp, typename _Proj = identity,
+            typename _Proj = identity,
+            typename _Tp _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_Iter, _Proj),
             indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>>
               _Comp = ranges::less>
       constexpr subrange<_Iter>
@@ -2177,7 +2215,9 @@ namespace ranges
       }
 
     template<forward_range _Range,
-            typename _Tp, typename _Proj = identity,
+            typename _Proj = identity,
+            typename _Tp
+              _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(iterator_t<_Range>, _Proj),
             indirect_strict_weak_order<const _Tp*,
                                        projected<iterator_t<_Range>, _Proj>>
               _Comp = ranges::less>
@@ -2195,7 +2235,8 @@ namespace ranges
   struct __binary_search_fn
   {
     template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
-            typename _Tp, typename _Proj = identity,
+            typename _Proj = identity,
+            typename _Tp _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_Iter, _Proj),
             indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>>
               _Comp = ranges::less>
       constexpr bool
@@ -2210,7 +2251,9 @@ namespace ranges
       }
 
     template<forward_range _Range,
-            typename _Tp, typename _Proj = identity,
+            typename _Proj = identity,
+            typename _Tp
+              _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(iterator_t<_Range>, _Proj),
             indirect_strict_weak_order<const _Tp*,
                                        projected<iterator_t<_Range>, _Proj>>
               _Comp = ranges::less>
@@ -3469,14 +3512,18 @@ namespace ranges
   struct __contains_fn
   {
     template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
-           typename _Tp, typename _Proj = identity>
+           typename _Proj = identity,
+           typename _Tp _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_Iter, _Proj)>
       requires indirect_binary_predicate<ranges::equal_to,
                                         projected<_Iter, _Proj>, const _Tp*>
       constexpr bool
       operator()(_Iter __first, _Sent __last, const _Tp& __value, _Proj __proj 
= {}) const
       { return ranges::find(std::move(__first), __last, __value, 
std::move(__proj)) != __last; }
 
-    template<input_range _Range, typename _Tp, typename _Proj = identity>
+    template<input_range _Range,
+           typename _Proj = identity,
+           typename _Tp
+             _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(iterator_t<_Range>, _Proj)>
       requires indirect_binary_predicate<ranges::equal_to,
                                         projected<iterator_t<_Range>, _Proj>, 
const _Tp*>
       constexpr bool
@@ -3525,7 +3572,9 @@ namespace ranges
 
   struct __find_last_fn
   {
-    template<forward_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Tp, 
typename _Proj = identity>
+    template<forward_iterator _Iter, sentinel_for<_Iter> _Sent,
+            typename _Proj = identity,
+            typename _Tp _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_Iter, _Proj)>
       requires indirect_binary_predicate<ranges::equal_to, projected<_Iter, 
_Proj>, const _Tp*>
       constexpr subrange<_Iter>
       operator()(_Iter __first, _Sent __last, const _Tp& __value, _Proj __proj 
= {}) const
@@ -3556,7 +3605,9 @@ namespace ranges
          }
       }
 
-    template<forward_range _Range, typename _Tp, typename _Proj = identity>
+    template<forward_range _Range, typename _Proj = identity,
+            typename _Tp
+              _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(iterator_t<_Range>, _Proj)>
       requires indirect_binary_predicate<ranges::equal_to, 
projected<iterator_t<_Range>, _Proj>, const _Tp*>
       constexpr borrowed_subrange_t<_Range>
       operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const
@@ -3730,7 +3781,8 @@ namespace ranges
        return _Ret{std::move(__first), std::move(__accum)};
       }
 
-    template<input_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Tp,
+    template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
+            typename _Tp _GLIBCXX26_DEF_VAL_T(iter_value_t<_Iter>),
             __detail::__indirectly_binary_left_foldable<_Tp, _Iter> _Fp>
       constexpr auto
       operator()(_Iter __first, _Sent __last, _Tp __init, _Fp __f) const
@@ -3740,7 +3792,8 @@ namespace ranges
                                  std::move(__init), std::move(__f));
       }
 
-    template<input_range _Range, typename _Tp,
+    template<input_range _Range,
+            typename _Tp _GLIBCXX26_DEF_VAL_T(range_value_t<_Range>),
             __detail::__indirectly_binary_left_foldable<_Tp, 
iterator_t<_Range>> _Fp>
       constexpr auto
       operator()(_Range&& __r, _Tp __init, _Fp __f) const
@@ -3755,7 +3808,8 @@ namespace ranges
 
   struct __fold_left_fn
   {
-    template<input_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Tp,
+    template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
+            typename _Tp _GLIBCXX26_DEF_VAL_T(iter_value_t<_Iter>),
             __detail::__indirectly_binary_left_foldable<_Tp, _Iter> _Fp>
       constexpr auto
       operator()(_Iter __first, _Sent __last, _Tp __init, _Fp __f) const
@@ -3764,7 +3818,8 @@ namespace ranges
                                           std::move(__init), 
std::move(__f)).value;
       }
 
-    template<input_range _Range, typename _Tp,
+    template<input_range _Range,
+            typename _Tp _GLIBCXX26_DEF_VAL_T(range_value_t<_Range>),
             __detail::__indirectly_binary_left_foldable<_Tp, 
iterator_t<_Range>> _Fp>
       constexpr auto
       operator()(_Range&& __r, _Tp __init, _Fp __f) const
@@ -3842,7 +3897,8 @@ namespace ranges
 
   struct __fold_right_fn
   {
-    template<bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent, typename 
_Tp,
+    template<bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent,
+            typename _Tp _GLIBCXX26_DEF_VAL_T(iter_value_t<_Iter>),
             __detail::__indirectly_binary_right_foldable<_Tp, _Iter> _Fp>
       constexpr auto
       operator()(_Iter __first, _Sent __last, _Tp __init, _Fp __f) const
@@ -3859,7 +3915,8 @@ namespace ranges
        return __accum;
       }
 
-    template<bidirectional_range _Range, typename _Tp,
+    template<bidirectional_range _Range,
+            typename _Tp _GLIBCXX26_DEF_VAL_T(range_value_t<_Range>),
             __detail::__indirectly_binary_right_foldable<_Tp, 
iterator_t<_Range>> _Fp>
       constexpr auto
       operator()(_Range&& __r, _Tp __init, _Fp __f) const
diff --git a/libstdc++-v3/include/bits/ranges_algobase.h 
b/libstdc++-v3/include/bits/ranges_algobase.h
index 9b45cbc5ef41..2a36ba69775a 100644
--- a/libstdc++-v3/include/bits/ranges_algobase.h
+++ b/libstdc++-v3/include/bits/ranges_algobase.h
@@ -532,7 +532,9 @@ namespace ranges
 
   struct __fill_n_fn
   {
-    template<typename _Tp, output_iterator<const _Tp&> _Out>
+    template<typename _Out,
+            typename _Tp _GLIBCXX26_DEF_VAL_T(iter_value_t<_Out>)>
+      requires output_iterator<_Out, const _Tp&>
       constexpr _Out
       operator()(_Out __first, iter_difference_t<_Out> __n,
                 const _Tp& __value) const
@@ -577,8 +579,10 @@ namespace ranges
 
   struct __fill_fn
   {
-    template<typename _Tp,
-            output_iterator<const _Tp&> _Out, sentinel_for<_Out> _Sent>
+    template<typename _Out,
+            sentinel_for<_Out> _Sent,
+            typename _Tp _GLIBCXX26_DEF_VAL_T(iter_value_t<_Out>)>
+      requires output_iterator<_Out, const _Tp&>
       constexpr _Out
       operator()(_Out __first, _Sent __last, const _Tp& __value) const
       {
@@ -604,7 +608,9 @@ namespace ranges
          }
       }
 
-    template<typename _Tp, output_range<const _Tp&> _Range>
+    template<typename _Range,
+            typename _Tp _GLIBCXX26_DEF_VAL_T(range_value_t<_Range>)>
+      requires output_range<_Range, const _Tp&>
       constexpr borrowed_iterator_t<_Range>
       operator()(_Range&& __r, const _Tp& __value) const
       {
diff --git a/libstdc++-v3/include/bits/ranges_base.h 
b/libstdc++-v3/include/bits/ranges_base.h
index 0c6a4e83bb24..ebd4f7e59569 100644
--- a/libstdc++-v3/include/bits/ranges_base.h
+++ b/libstdc++-v3/include/bits/ranges_base.h
@@ -42,6 +42,12 @@
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wpedantic" // __int128
 
+#if __glibcxx_algorithm_default_value_type // C++ >= 26
+# define _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_I, _P) = projected_value_t<_I, _P>
+#else
+# define _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_I, _P)
+#endif
+
 #ifdef __cpp_lib_concepts
 namespace std _GLIBCXX_VISIBILITY(default)
 {
diff --git a/libstdc++-v3/include/bits/ranges_util.h 
b/libstdc++-v3/include/bits/ranges_util.h
index e6d96073e87b..3f191e6d446a 100644
--- a/libstdc++-v3/include/bits/ranges_util.h
+++ b/libstdc++-v3/include/bits/ranges_util.h
@@ -487,8 +487,9 @@ namespace ranges
 {
   struct __find_fn
   {
-    template<input_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Tp,
-            typename _Proj = identity>
+    template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
+            typename _Proj = identity,
+            typename _Tp _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_Iter, _Proj)>
       requires indirect_binary_predicate<ranges::equal_to,
                                         projected<_Iter, _Proj>, const _Tp*>
       constexpr _Iter
@@ -521,7 +522,9 @@ namespace ranges
        return __first;
       }
 
-    template<input_range _Range, typename _Tp, typename _Proj = identity>
+    template<input_range _Range, typename _Proj = identity,
+            typename _Tp
+            _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(iterator_t<_Range>, _Proj)>
       requires indirect_binary_predicate<ranges::equal_to,
                                         projected<iterator_t<_Range>, _Proj>,
                                         const _Tp*>
diff --git a/libstdc++-v3/include/bits/stl_iterator_base_types.h 
b/libstdc++-v3/include/bits/stl_iterator_base_types.h
index 07beec3554d2..14ea0d44e285 100644
--- a/libstdc++-v3/include/bits/stl_iterator_base_types.h
+++ b/libstdc++-v3/include/bits/stl_iterator_base_types.h
@@ -269,4 +269,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
 
+#if __glibcxx_algorithm_default_value_type // C++ >= 26
+# define _GLIBCXX26_DEF_VAL_T(T) = T
+# define _GLIBCXX26_ALGO_DEF_VAL_T(_Iterator) \
+     = typename iterator_traits<_Iterator>::value_type
+#else
+# define _GLIBCXX26_DEF_VAL_T(T)
+# define _GLIBCXX26_ALGO_DEF_VAL_T(_Iterator)
+#endif
+
 #endif /* _STL_ITERATOR_BASE_TYPES_H */
diff --git a/libstdc++-v3/include/bits/version.def 
b/libstdc++-v3/include/bits/version.def
index 36f9ea429c4d..c12b0de61598 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -1781,6 +1781,14 @@ ftms = {
   };
 };
 
+ftms = {
+  name = algorithm_default_value_type;
+  values = {
+    v = 202403;
+    cxxmin = 26;
+  };
+};
+
 ftms = {
   name = fstream_native_handle;
   values = {
diff --git a/libstdc++-v3/include/bits/version.h 
b/libstdc++-v3/include/bits/version.h
index fb97e67fb992..4738def977fe 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -1968,6 +1968,16 @@
 #endif /* !defined(__cpp_lib_unreachable) && 
defined(__glibcxx_want_unreachable) */
 #undef __glibcxx_want_unreachable
 
+#if !defined(__cpp_lib_algorithm_default_value_type)
+# if (__cplusplus >  202302L)
+#  define __glibcxx_algorithm_default_value_type 202403L
+#  if defined(__glibcxx_want_all) || 
defined(__glibcxx_want_algorithm_default_value_type)
+#   define __cpp_lib_algorithm_default_value_type 202403L
+#  endif
+# endif
+#endif /* !defined(__cpp_lib_algorithm_default_value_type) && 
defined(__glibcxx_want_algorithm_default_value_type) */
+#undef __glibcxx_want_algorithm_default_value_type
+
 #if !defined(__cpp_lib_fstream_native_handle)
 # if (__cplusplus >  202302L) && _GLIBCXX_HOSTED
 #  define __glibcxx_fstream_native_handle 202306L
diff --git a/libstdc++-v3/include/pstl/glue_algorithm_defs.h 
b/libstdc++-v3/include/pstl/glue_algorithm_defs.h
index cef78e22e31c..e5260e15a1aa 100644
--- a/libstdc++-v3/include/pstl/glue_algorithm_defs.h
+++ b/libstdc++-v3/include/pstl/glue_algorithm_defs.h
@@ -10,6 +10,7 @@
 #ifndef _PSTL_GLUE_ALGORITHM_DEFS_H
 #define _PSTL_GLUE_ALGORITHM_DEFS_H
 
+#include <bits/stl_iterator_base_types.h>
 #include <bits/stl_pair.h>
 
 #include "execution_defs.h"
@@ -55,7 +56,7 @@ template <class _ExecutionPolicy, class _ForwardIterator, 
class _Predicate>
 __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, 
_ForwardIterator>
 find_if_not(_ExecutionPolicy&& __exec, _ForwardIterator __first, 
_ForwardIterator __last, _Predicate __pred);
 
-template <class _ExecutionPolicy, class _ForwardIterator, class _Tp>
+template <class _ExecutionPolicy, class _ForwardIterator, class _Tp 
_GLIBCXX26_ALGO_DEF_VAL_T(_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_ALGO_DEF_VAL_T(_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_ALGO_DEF_VAL_T(_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_ALGO_DEF_VAL_T(_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_ALGO_DEF_VAL_T(_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_ALGO_DEF_VAL_T(_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_ALGO_DEF_VAL_T(_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_ALGO_DEF_VAL_T(_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_ALGO_DEF_VAL_T(_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_ALGO_DEF_VAL_T(_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_ALGO_DEF_VAL_T(_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 163e6b5dca72..b410e7c281b5 100644
--- a/libstdc++-v3/include/std/algorithm
+++ b/libstdc++-v3/include/std/algorithm
@@ -63,6 +63,7 @@
 # include <bits/ranges_algo.h>
 #endif
 
+#define __glibcxx_want_algorithm_default_value_type
 #define __glibcxx_want_clamp
 #define __glibcxx_want_constexpr_algorithms
 #define __glibcxx_want_freestanding_algorithm
diff --git a/libstdc++-v3/include/std/deque b/libstdc++-v3/include/std/deque
index 69f8c0dcdccf..e45dd069952f 100644
--- a/libstdc++-v3/include/std/deque
+++ b/libstdc++-v3/include/std/deque
@@ -68,6 +68,7 @@
 #include <bits/range_access.h>
 #include <bits/deque.tcc>
 
+#define __glibcxx_want_algorithm_default_value_type
 #define __glibcxx_want_allocator_traits_is_always_equal
 #define __glibcxx_want_erase_if
 #define __glibcxx_want_nonmember_container_access
@@ -116,7 +117,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return 0;
     }
 
-  template<typename _Tp, typename _Alloc, typename _Up>
+  template<typename _Tp, typename _Alloc,
+          typename _Up _GLIBCXX26_DEF_VAL_T(_Tp)>
     inline typename deque<_Tp, _Alloc>::size_type
     erase(deque<_Tp, _Alloc>& __cont, const _Up& __value)
     {
diff --git a/libstdc++-v3/include/std/forward_list 
b/libstdc++-v3/include/std/forward_list
index dfd7d48d1219..5341d1a82391 100644
--- a/libstdc++-v3/include/std/forward_list
+++ b/libstdc++-v3/include/std/forward_list
@@ -45,6 +45,7 @@
 # include <debug/forward_list>
 #endif
 
+#define __glibcxx_want_algorithm_default_value_type
 #define __glibcxx_want_allocator_traits_is_always_equal
 #define __glibcxx_want_erase_if
 #define __glibcxx_want_incomplete_container_elements
@@ -75,7 +76,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     erase_if(forward_list<_Tp, _Alloc>& __cont, _Predicate __pred)
     { return __cont.remove_if(__pred); }
 
-  template<typename _Tp, typename _Alloc, typename _Up>
+  template<typename _Tp, typename _Alloc,
+          typename _Up _GLIBCXX26_DEF_VAL_T(_Tp)>
     inline typename forward_list<_Tp, _Alloc>::size_type
     erase(forward_list<_Tp, _Alloc>& __cont, const _Up& __value)
     {
diff --git a/libstdc++-v3/include/std/list b/libstdc++-v3/include/std/list
index ff632fc1ab2f..7b67cebe74cf 100644
--- a/libstdc++-v3/include/std/list
+++ b/libstdc++-v3/include/std/list
@@ -69,6 +69,7 @@
 # include <debug/list>
 #endif
 
+#define __glibcxx_want_algorithm_default_value_type
 #define __glibcxx_want_allocator_traits_is_always_equal
 #define __glibcxx_want_erase_if
 #define __glibcxx_want_incomplete_container_elements
@@ -99,7 +100,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     erase_if(list<_Tp, _Alloc>& __cont, _Predicate __pred)
     { return __cont.remove_if(__pred); }
 
-  template<typename _Tp, typename _Alloc, typename _Up>
+  template<typename _Tp, typename _Alloc,
+          typename _Up _GLIBCXX26_DEF_VAL_T(_Tp)>
     inline typename list<_Tp, _Alloc>::size_type
     erase(list<_Tp, _Alloc>& __cont, const _Up& __value)
     {
diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
index aa08a48440cf..7169c3a92aa5 100644
--- a/libstdc++-v3/include/std/ranges
+++ b/libstdc++-v3/include/std/ranges
@@ -51,6 +51,7 @@
 #include <bits/ranges_util.h>
 #include <bits/refwrap.h>
 
+#define __glibcxx_want_algorithm_default_value_type
 #define __glibcxx_want_ranges
 #define __glibcxx_want_ranges_as_const
 #define __glibcxx_want_ranges_as_rvalue
diff --git a/libstdc++-v3/include/std/string b/libstdc++-v3/include/std/string
index 8db0802a2827..44a39da50663 100644
--- a/libstdc++-v3/include/std/string
+++ b/libstdc++-v3/include/std/string
@@ -54,6 +54,7 @@
 #include <bits/basic_string.h>
 #include <bits/basic_string.tcc>
 
+#define __glibcxx_want_algorithm_default_value_type
 #define __glibcxx_want_allocator_traits_is_always_equal
 #define __glibcxx_want_constexpr_char_traits
 #define __glibcxx_want_constexpr_string
@@ -105,7 +106,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return __osz - __cont.size();
     }
 
-  template<typename _CharT, typename _Traits, typename _Alloc, typename _Up>
+  template<typename _CharT, typename _Traits, typename _Alloc,
+          typename _Up _GLIBCXX26_DEF_VAL_T(_CharT)>
     _GLIBCXX20_CONSTEXPR
     inline typename basic_string<_CharT, _Traits, _Alloc>::size_type
     erase(basic_string<_CharT, _Traits, _Alloc>& __cont, const _Up& __value)
diff --git a/libstdc++-v3/include/std/vector b/libstdc++-v3/include/std/vector
index 906c16279359..a9894d7e8a8d 100644
--- a/libstdc++-v3/include/std/vector
+++ b/libstdc++-v3/include/std/vector
@@ -76,6 +76,7 @@
 # include <debug/vector>
 #endif
 
+#define __glibcxx_want_algorithm_default_value_type
 #define __glibcxx_want_allocator_traits_is_always_equal
 #define __glibcxx_want_constexpr_vector
 #define __glibcxx_want_erase_if
@@ -129,7 +130,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return 0;
     }
 
-  template<typename _Tp, typename _Alloc, typename _Up>
+  template<typename _Tp, typename _Alloc,
+          typename _Up _GLIBCXX26_DEF_VAL_T(_Tp)>
     _GLIBCXX20_CONSTEXPR
     inline typename vector<_Tp, _Alloc>::size_type
     erase(vector<_Tp, _Alloc>& __cont, const _Up& __value)
diff --git a/libstdc++-v3/testsuite/23_containers/default_template_value.cc 
b/libstdc++-v3/testsuite/23_containers/default_template_value.cc
new file mode 100644
index 000000000000..b7615032686d
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/default_template_value.cc
@@ -0,0 +1,40 @@
+// { dg-do compile { target c++26 } }
+
+#include <deque>
+#include <forward_list>
+#include <list>
+#include <string>
+#include <vector>
+
+#if !defined(__cpp_lib_algorithm_default_value_type)
+#error "Feature test macro for default template type for algorithms' values is 
missing"
+#elif __cpp_lib_algorithm_default_value_type < 202403L
+#error "Feature test macro for default template type for algorithms' values is 
wrong"
+#endif
+
+struct S {
+  S(int, double);
+  friend auto operator<=>(const S&, const S&) = default;
+};
+
+template<template<typename...> typename Container>
+void test_erase()
+{
+  Container<S> c;
+  std::erase(c, {1, 3.14});
+}
+
+void
+test()
+{
+  test_erase<std::deque>();
+  test_erase<std::forward_list>();
+  test_erase<std::list>();
+  test_erase<std::vector>();
+
+  std::string s;
+  std::erase(s, {'x'});
+
+  std::wstring ws;
+  std::erase(ws, {L'x'});
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/default_template_value.cc 
b/libstdc++-v3/testsuite/25_algorithms/default_template_value.cc
new file mode 100644
index 000000000000..3cf51bc087b4
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/default_template_value.cc
@@ -0,0 +1,142 @@
+// { dg-do compile { target c++26 } }
+
+#include <algorithm>
+
+#if !defined(__cpp_lib_algorithm_default_value_type)
+#error "Feature test macro for default template type for algorithms' values is 
missing"
+#elif __cpp_lib_algorithm_default_value_type < 202403L
+#error "Feature test macro for default template type for algorithms' values is 
wrong"
+#endif
+
+#include <execution>
+#include <ranges>
+#include <iterator>
+#include <vector>
+
+// Conversions from Input to Output will be used in certain algorithms.
+// Make Output have a different number of arguments to its constructor
+// so we can check whether a braced-init-list is indeed matching Input
+// or Output
+struct Output
+{
+  Output(char, float, long);
+};
+
+#define OUTPUT_VAL {'x', 1.171f, 10L}
+
+struct Input
+{
+  Input(int, double);
+  friend bool operator<=>(const Input &, const Input &) = default;
+  friend Input operator+(const Input &, const Input &);
+  operator Output() const;
+};
+
+#define INPUT_VAL {1, 3.14}
+
+void
+test()
+{
+  extern std::vector<Input> in;
+  extern std::vector<Output> out;
+
+  const auto pred = [](auto &&) { return true; };
+
+  // [alg.find]
+  (void) std::find(in.begin(), in.end(), INPUT_VAL);
+  (void) std::find(std::execution::seq, in.begin(), in.end(), INPUT_VAL);
+  (void) std::ranges::find(in.begin(), in.end(), INPUT_VAL);
+  (void) std::ranges::find(in, INPUT_VAL);
+
+  // [alg.count]
+  (void) std::count(in.begin(), in.end(), INPUT_VAL);
+  (void) std::count(std::execution::seq, in.begin(), in.end(), INPUT_VAL);
+  (void) std::ranges::count(in.begin(), in.end(), INPUT_VAL);
+  (void) std::ranges::count(in, INPUT_VAL);
+
+  // [alg.search]
+  (void) std::search_n(in.begin(), in.end(), 10, INPUT_VAL);
+  (void) std::search_n(in.begin(), in.end(), 10, INPUT_VAL, std::equal_to{});
+  (void) std::search_n(std::execution::seq, in.begin(), in.end(), 10, 
INPUT_VAL);
+  (void) std::search_n(std::execution::seq, in.begin(), in.end(), 10, 
INPUT_VAL, std::equal_to{});
+  (void) std::ranges::search_n(in.begin(), in.end(), 10, INPUT_VAL);
+  (void) std::ranges::search_n(in, 10, INPUT_VAL);
+
+  // [alg.replace]
+  (void) std::replace(in.begin(), in.end(), INPUT_VAL, INPUT_VAL);
+  (void) std::replace(std::execution::seq, in.begin(), in.end(), INPUT_VAL, 
INPUT_VAL);
+  (void) std::replace_if(in.begin(), in.end(), pred, INPUT_VAL);
+  (void) std::replace_if(std::execution::seq, in.begin(), in.end(), pred, 
INPUT_VAL);
+
+  (void) std::ranges::replace(in.begin(), in.end(), INPUT_VAL, INPUT_VAL);
+  (void) std::ranges::replace(in, INPUT_VAL, INPUT_VAL);
+  (void) std::ranges::replace_if(in.begin(), in.end(), pred, INPUT_VAL);
+  (void) std::ranges::replace_if(in, pred, INPUT_VAL);
+
+  (void) std::replace_copy_if(in.begin(), in.end(), out.begin(), pred, 
OUTPUT_VAL);
+  (void) std::replace_copy_if(std::execution::seq, in.begin(), in.end(), 
out.begin(), pred, OUTPUT_VAL);
+  (void) std::ranges::replace_copy_if(in.begin(), in.end(), out.begin(), pred, 
OUTPUT_VAL);
+  (void) std::ranges::replace_copy_if(in, out.begin(), pred, OUTPUT_VAL);
+
+  // Non-range replace_copy is deliberately skipped by P2248
+  (void) std::ranges::replace_copy(in.begin(), in.end(), out.begin(), 
INPUT_VAL, OUTPUT_VAL);
+  (void) std::ranges::replace_copy(in, out.begin(), INPUT_VAL, OUTPUT_VAL);
+
+  // [alg.fill]
+  (void) std::fill(in.begin(), in.end(), INPUT_VAL);
+  (void) std::fill(std::execution::seq, in.begin(), in.end(), INPUT_VAL);
+  (void) std::ranges::fill(in.begin(), in.end(), INPUT_VAL);
+  (void) std::ranges::fill(in, INPUT_VAL);
+
+  (void) std::fill_n(in.begin(), 10, INPUT_VAL);
+  (void) std::fill_n(std::execution::seq, in.begin(), 10, INPUT_VAL);
+  (void) std::ranges::fill_n(in.begin(), 10, INPUT_VAL);
+
+  // [alg.remove]
+  (void) std::remove(in.begin(), in.end(), INPUT_VAL);
+  (void) std::remove(std::execution::seq, in.begin(), in.end(), INPUT_VAL);
+  (void) std::ranges::remove(in.begin(), in.end(), INPUT_VAL);
+  (void) std::ranges::remove(in, INPUT_VAL);
+
+  (void) std::remove_copy(in.begin(), in.end(), out.begin(), INPUT_VAL);
+  (void) std::remove_copy(std::execution::seq, in.begin(), in.end(), 
out.begin(), INPUT_VAL);
+  (void) std::ranges::remove_copy(in.begin(), in.end(), out.begin(), 
INPUT_VAL);
+  (void) std::ranges::remove_copy(in, out.begin(), INPUT_VAL);
+
+  // [alg.binary.search]
+  (void) std::lower_bound(in.begin(), in.end(), INPUT_VAL);
+  (void) std::lower_bound(in.begin(), in.end(), INPUT_VAL, std::less{});
+  (void) std::ranges::lower_bound(in.begin(), in.end(), INPUT_VAL);
+  (void) std::ranges::lower_bound(in, INPUT_VAL);
+
+  (void) std::upper_bound(in.begin(), in.end(), INPUT_VAL);
+  (void) std::upper_bound(in.begin(), in.end(), INPUT_VAL, std::less{});
+  (void) std::ranges::upper_bound(in.begin(), in.end(), INPUT_VAL);
+  (void) std::ranges::upper_bound(in, INPUT_VAL);
+
+  (void) std::equal_range(in.begin(), in.end(), INPUT_VAL);
+  (void) std::equal_range(in.begin(), in.end(), INPUT_VAL, std::less{});
+  (void) std::ranges::equal_range(in.begin(), in.end(), INPUT_VAL);
+  (void) std::ranges::equal_range(in, INPUT_VAL);
+
+  (void) std::binary_search(in.begin(), in.end(), INPUT_VAL);
+  (void) std::binary_search(in.begin(), in.end(), INPUT_VAL, std::less{});
+  (void) std::ranges::binary_search(in.begin(), in.end(), INPUT_VAL);
+  (void) std::ranges::binary_search(in, INPUT_VAL);
+
+  // [alg.fold]
+  (void) std::ranges::fold_left(in.begin(), in.end(), INPUT_VAL, 
std::plus<>{});
+  (void) std::ranges::fold_left(in, INPUT_VAL, std::plus<>{});
+  (void) std::ranges::fold_right(in.begin(), in.end(), INPUT_VAL, 
std::plus<>{});
+  (void) std::ranges::fold_right(in, INPUT_VAL, std::plus<>{});
+  (void) std::ranges::fold_left_with_iter(in.begin(), in.end(), INPUT_VAL, 
std::plus<>{});
+  (void) std::ranges::fold_left_with_iter(in, INPUT_VAL, std::plus<>{});
+
+  // [alg.contains]
+  (void) std::ranges::contains(in.begin(), in.end(), INPUT_VAL);
+  (void) std::ranges::contains(in, INPUT_VAL);
+
+  // [alg.find.last]
+  (void) std::ranges::find_last(in.begin(), in.end(), INPUT_VAL);
+  (void) std::ranges::find_last(in, INPUT_VAL);
+}

Reply via email to