[gcc(refs/users/marxin/heads/marxin-gcc-benchmark-branch)] libstdc++: LWG 3301 transform_view::iterator has incorrect iterator_category

Martin Liska marxin@gcc.gnu.org
Mon Mar 30 10:21:52 GMT 2020


https://gcc.gnu.org/g:510bd1c178f3719df7148dd584d30acc2595dc3c

commit 510bd1c178f3719df7148dd584d30acc2595dc3c
Author: Patrick Palka <ppalka@redhat.com>
Date:   Mon Feb 24 16:38:07 2020 -0500

    libstdc++: LWG 3301 transform_view::iterator has incorrect iterator_category
    
    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.

Diff:
---
 libstdc++-v3/ChangeLog                             |  5 +++++
 libstdc++-v3/include/std/ranges                    | 16 ++++++++++-----
 .../testsuite/std/ranges/adaptors/transform.cc     | 24 ++++++++++++++++++++++
 3 files changed, 40 insertions(+), 5 deletions(-)

diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 046d50de6d1..1a56a7d221c 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -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.
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..178544d6378 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 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();
 }


More information about the Libstdc++-cvs mailing list