libstdc++-v3/ChangeLog:

        LWG 3301 transform_view::_Iterator has incorrect iterator_category
        * include/std/ranges (transform_view::_Iterator::_S_iter_cat): Adjust
        determination of iterator_category as per LWG 3301.
        * testsuite/std/ranges/adaptors/transform.cc: Augment test.
---
 libstdc++-v3/include/std/ranges               | 16 +++++++++----
 .../std/ranges/adaptors/transform.cc          | 24 +++++++++++++++++++
 2 files changed, 35 insertions(+), 5 deletions(-)

diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
index ab8fbaca38f..aed90e9710e 100644
--- a/libstdc++-v3/include/std/ranges
+++ b/libstdc++-v3/include/std/ranges
@@ -1570,12 +1570,18 @@ namespace views
          static constexpr auto
          _S_iter_cat()
          {
-           using _Cat
-              = typename iterator_traits<_Base_iter>::iterator_category;
-           if constexpr (derived_from<_Cat, contiguous_iterator_tag>)
-             return random_access_iterator_tag{};
+           using _Res = invoke_result_t<_Fp&, range_reference_t<_Base>>;
+           if constexpr (is_lvalue_reference_v<_Res>)
+             {
+               using _Cat
+                 = typename iterator_traits<_Base_iter>::iterator_category;
+               if constexpr (derived_from<_Cat, contiguous_iterator_tag>)
+                 return random_access_iterator_tag{};
+               else
+                 return _Cat{};
+             }
            else
-             return _Cat{};
+             return input_iterator_tag{};
          }
 
          static constexpr decltype(auto)
diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc 
b/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc
index ad51fffb43d..0845febe2cf 100644
--- a/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc
+++ b/libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc
@@ -77,10 +77,34 @@ test03()
   VERIFY( ranges::equal(v, (int[]){1,2,3,4,5}) );
 }
 
+void
+test04()
+{
+  // LWG 3302
+    {
+      auto f = [] (int x) { return x; };
+      int x[] = {1,2,3,4,5};
+      auto v = x | views::transform(f);
+      auto i = v.begin();
+      using Cat = decltype(i)::iterator_category;
+      static_assert(std::same_as<Cat, std::input_iterator_tag>);
+    }
+
+    {
+      auto f = [] (int &x) -> int& { return x; };
+      int x[] = {1,2,3,4,5};
+      auto v = x | views::transform(f);
+      auto i = v.begin();
+      using Cat = decltype(i)::iterator_category;
+      static_assert(std::derived_from<Cat, std::forward_iterator_tag>);
+    }
+}
+
 int
 main()
 {
   test01();
   test02();
   test03();
+  test04();
 }
-- 
2.25.1.291.ge68e29171c

Reply via email to