Implement the resolution of LWG 444, accepted in Kona 2025.

The new value to be assigned to the matching elements should default to
the value type of the range, not the type returned by the projection.
The type returned by the projection is only used to find the matching
elements, and might not be assignable to the value type at all.

libstdc++-v3/ChangeLog:

        * include/bits/ranges_algo.h (__replace_fn, __replace_if_fn):
        Change default template argument for type of new value, as per
        LWG 4444.
        * testsuite/25_algorithms/replace/lwg4444.cc: New test.
        * testsuite/25_algorithms/replace_if/lwg4444.cc: New test.
---

Tested x86_64-linux.

 libstdc++-v3/include/bits/ranges_algo.h       |  8 ++---
 .../25_algorithms/replace/lwg4444.cc          | 30 ++++++++++++++++++
 .../25_algorithms/replace_if/lwg4444.cc       | 31 +++++++++++++++++++
 3 files changed, 65 insertions(+), 4 deletions(-)
 create mode 100644 libstdc++-v3/testsuite/25_algorithms/replace/lwg4444.cc
 create mode 100644 libstdc++-v3/testsuite/25_algorithms/replace_if/lwg4444.cc

diff --git a/libstdc++-v3/include/bits/ranges_algo.h 
b/libstdc++-v3/include/bits/ranges_algo.h
index 54f0ac8545c5..0d1928d52a2f 100644
--- a/libstdc++-v3/include/bits/ranges_algo.h
+++ b/libstdc++-v3/include/bits/ranges_algo.h
@@ -1073,7 +1073,7 @@ namespace ranges
     template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
             typename _Proj = identity,
             typename _Tp1 _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_Iter, _Proj),
-            typename _Tp2 _GLIBCXX26_DEF_VAL_T(_Tp1)>
+            typename _Tp2 _GLIBCXX26_DEF_VAL_T(iter_value_t<_Iter>)>
       requires indirectly_writable<_Iter, const _Tp2&>
        && indirect_binary_predicate<ranges::equal_to, projected<_Iter, _Proj>,
                                     const _Tp1*>
@@ -1091,7 +1091,7 @@ namespace ranges
     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)>
+            typename _Tp2 _GLIBCXX26_DEF_VAL_T(range_value_t<_Range>)>
       requires indirectly_writable<iterator_t<_Range>, const _Tp2&>
        && indirect_binary_predicate<ranges::equal_to,
                                     projected<iterator_t<_Range>, _Proj>,
@@ -1112,7 +1112,7 @@ namespace ranges
   {
     template<input_iterator _Iter, sentinel_for<_Iter> _Sent,
             typename _Proj = identity,
-            typename _Tp _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_Iter, _Proj),
+            typename _Tp _GLIBCXX26_DEF_VAL_T(iter_value_t<_Iter>),
             indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
       requires indirectly_writable<_Iter, const _Tp&>
       constexpr _Iter
@@ -1127,7 +1127,7 @@ namespace ranges
 
     template<input_range _Range, typename _Proj = identity,
             typename _Tp
-              _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(iterator_t<_Range>, _Proj),
+              _GLIBCXX26_DEF_VAL_T(range_value_t<_Range>),
             indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>>
               _Pred>
       requires indirectly_writable<iterator_t<_Range>, const _Tp&>
diff --git a/libstdc++-v3/testsuite/25_algorithms/replace/lwg4444.cc 
b/libstdc++-v3/testsuite/25_algorithms/replace/lwg4444.cc
new file mode 100644
index 000000000000..a870815e83c9
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/replace/lwg4444.cc
@@ -0,0 +1,30 @@
+// { dg-do run { target c++26 } }
+
+// LWG 4444. Fix default template arguments for ranges::replace [...]
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+
+struct S { int i; int j; };
+
+void
+test_replace_iters()
+{
+  S s[2] = { {10, 11}, {20, 22} };
+  std::ranges::replace(s, s+2, 20, {30, 33}, &S::i);
+  VERIFY( s[1].j == 33 );
+}
+
+void
+test_replace_range()
+{
+  S s[2] = { {10, 11}, {20, 22} };
+  std::ranges::replace(s, 20, {40, 44}, &S::i);
+  VERIFY( s[1].j == 44 );
+}
+
+int main()
+{
+  test_replace_iters();
+  test_replace_range();
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/replace_if/lwg4444.cc 
b/libstdc++-v3/testsuite/25_algorithms/replace_if/lwg4444.cc
new file mode 100644
index 000000000000..bcc58fa7e959
--- /dev/null
+++ b/libstdc++-v3/testsuite/25_algorithms/replace_if/lwg4444.cc
@@ -0,0 +1,31 @@
+// { dg-do run { target c++26 } }
+
+// LWG 4444. Fix default template arguments for [...] ranges::replace_if
+
+#include <algorithm>
+#include <testsuite_hooks.h>
+
+struct S { int i; int j; };
+auto twenty = [](int i) { return i == 20; };
+
+void
+test_replace_if_iters()
+{
+  S s[2] = { {10, 11}, {20, 22} };
+  std::ranges::replace_if(s, s+2, twenty, {30, 33}, &S::i);
+  VERIFY( s[1].j == 33 );
+}
+
+void
+test_replace_if_range()
+{
+  S s[2] = { {10, 11}, {20, 22} };
+  std::ranges::replace_if(s, twenty, {40, 44}, &S::i);
+  VERIFY( s[1].j == 44 );
+}
+
+int main()
+{
+  test_replace_if_iters();
+  test_replace_if_range();
+}
-- 
2.53.0

Reply via email to