libstdc++: LWG 3301 transform_view::iterator has incorrect iterator_category
authorPatrick Palka <ppalka@redhat.com>
Mon, 24 Feb 2020 21:38:07 +0000 (16:38 -0500)
committerPatrick Palka <ppalka@redhat.com>
Tue, 25 Feb 2020 18:04:32 +0000 (13:04 -0500)
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/ChangeLog
libstdc++-v3/include/std/ranges
libstdc++-v3/testsuite/std/ranges/adaptors/transform.cc

index 046d50de6d1755984e6d9a6520814ab7a254be31..1a56a7d221c9be4aba1aea3d915b8b1c74ab143a 100644 (file)
@@ -1,5 +1,10 @@
 2020-02-25  Patrick Palka  <ppalka@redhat.com>
 
+       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.
+
        LWG 3292 iota_view is under-constrained
        * include/std/ranges (iota_view): Require that _Winc models semiregular
          as per LWG 3292.
index ab8fbaca38f6c36058bcaaf4c7ded1111a6c0422..aed90e9710e1ffc671f0c3dd69df05ac5534b22e 100644 (file)
@@ -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)
index ad51fffb43dd6ab105a7f46ff896fb9f64919df2..178544d6378f05b93209f71f14740a2b9a6a9aaa 100644 (file)
@@ -77,10 +77,34 @@ test03()
   VERIFY( ranges::equal(v, (int[]){1,2,3,4,5}) );
 }
 
+void
+test04()
+{
+  // LWG 3301
+    {
+      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();
 }