[gcc r14-10793] libstdc++: Implement LWG 3564 for ranges::transform_view

Jonathan Wakely redi@gcc.gnu.org
Wed Oct 16 10:39:01 GMT 2024


https://gcc.gnu.org/g:4d8a55ac552627ebf9bf50d28a35459cba58d8c6

commit r14-10793-g4d8a55ac552627ebf9bf50d28a35459cba58d8c6
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Sun Oct 13 21:47:14 2024 +0100

    libstdc++: Implement LWG 3564 for ranges::transform_view
    
    The _Iterator<true> type returned by begin() const uses const F& to
    transform the elements, so it should use const F& to determine the
    iterator's value_type and iterator_category as well.
    
    This was accepted into the WP in July 2022.
    
    libstdc++-v3/ChangeLog:
    
            * include/std/ranges (transform_view:_Iterator): Use const F&
            to determine value_type and iterator_category of
            _Iterator<true>, as per LWG 3564.
            * testsuite/std/ranges/adaptors/transform.cc: Check value_type
            and iterator_category.
    
    Reviewed-by: Patrick Palka <ppalka@redhat.com>
    (cherry picked from commit dde19c600c3c8a1d765c9b4961d2556e89edad14)

Diff:
---
 libstdc++-v3/include/std/ranges                       |  9 +++++++--
 .../testsuite/std/ranges/adaptors/transform.cc        | 19 +++++++++++++++++++
 2 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
index 59a251536208..2c8a8535d396 100644
--- a/libstdc++-v3/include/std/ranges
+++ b/libstdc++-v3/include/std/ranges
@@ -1870,8 +1870,12 @@ namespace views::__adaptor
 	  static auto
 	  _S_iter_cat()
 	  {
+	    // _GLIBCXX_RESOLVE_LIB_DEFECTS
+	    // 3564. transform_view::iterator<true>::value_type and
+	    // iterator_category should use const F&
 	    using _Base = transform_view::_Base<_Const>;
-	    using _Res = invoke_result_t<_Fp&, range_reference_t<_Base>>;
+	    using _Res = invoke_result_t<__maybe_const_t<_Const, _Fp>&,
+					 range_reference_t<_Base>>;
 	    if constexpr (is_lvalue_reference_v<_Res>)
 	      {
 		using _Cat
@@ -1920,7 +1924,8 @@ namespace views::__adaptor
 	  using iterator_concept = decltype(_S_iter_concept());
 	  // iterator_category defined in __transform_view_iter_cat
 	  using value_type
-	    = remove_cvref_t<invoke_result_t<_Fp&, range_reference_t<_Base>>>;
+	    = remove_cvref_t<invoke_result_t<__maybe_const_t<_Const, _Fp>&,
+					     range_reference_t<_Base>>>;
 	  using difference_type = range_difference_t<_Base>;
 
 	  _Iterator() requires default_initializable<_Base_iter> = default;
diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc
index bcb18a3fc6c8..ca695349650a 100644
--- a/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc
@@ -196,6 +196,24 @@ test09()
 #endif
 }
 
+void
+test10()
+{
+  struct F {
+    short operator()(int) { return 0; }
+    const int& operator()(const int& i) const { return i; }
+  };
+
+  int x[] {2, 4};
+  const auto xform = x | views::transform(F{});
+  using const_iterator = decltype(xform.begin());
+  // LWG 3564. transform_view::iterator<true>::value_type and iterator_category
+  // should use const F&
+  static_assert(std::same_as<std::iter_value_t<const_iterator>, int>);
+  using cat = std::iterator_traits<const_iterator>::iterator_category;
+  static_assert(std::same_as<cat, std::random_access_iterator_tag>);
+}
+
 int
 main()
 {
@@ -208,4 +226,5 @@ main()
   test07();
   test08();
   test09();
+  test10();
 }


More information about the Libstdc++-cvs mailing list