On Thu, 20 Feb 2020, Jonathan Wakely wrote:

> On 19/02/20 23:53 -0500, Patrick Palka wrote:
> > We are forwarding the second argument of views::iota using the wrong type,
> > causing compiling errors when calling it with a value and bound of different
> > types, like in the test case below.
> 
> Good catch, OK for master.

Oops, the second patch in this series includes a friendship change that
should instead be a part of this patch: iota_view::_Iterator must
befriend iota_view::_Sentinel, so that iota_view::_Sentinel::operator==
can access its private members.  This is needed for the new test in
iota_view.cc to compile.

Tested on x86_64-pc-linux-gnu, does this look OK to commit?

-- >8 --

Subject: [PATCH] libstdc++: Forward second argument of views::iota using the
 correct type

We are forwarding the second argument of views::iota using the wrong type,
causing compile errors when calling views::iota with a value and bound of
different types, like in the test case below.

libstdc++-v3/ChangeLog:

        * include/std/ranges (iota_view): Forward declare _Sentinel.
        (iota_view::_Iterator): Befriend _Sentinel.
        (iota_view::_Sentinel::_M_equal): New member function.
        (iota_view::_Sentinel::operator==): Use it.
        (views::_Iota::operator()): Forward __f using the correct type.
        * testsuite/std/ranges/access/ssize.cc (test06): Don't call views::iota
        with integers of different signedness, to appease iota_view's deduction
        guide.
        * testsuite/std/ranges/iota/iota_view.cc: Augment test.
---
 libstdc++-v3/ChangeLog                          |  9 +++++++++
 libstdc++-v3/include/std/ranges                 | 12 ++++++++++--
 .../testsuite/std/ranges/access/ssize.cc        |  2 +-
 .../testsuite/std/ranges/iota/iota_view.cc      | 17 +++++++++++++++++
 4 files changed, 37 insertions(+), 3 deletions(-)

diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 30cf706cdae..90098fa9aa5 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,12 @@
+2020-02-20  Patrick Palka  <ppa...@redhat.com>
+
+       * include/std/ranges (views::_Iota::operator()): Forward __f using the
+       correct type.
+       * testsuite/std/ranges/access/ssize.cc (test06): Don't call views::iota
+       with integers of different signedness, to appease iota_view's deduction
+       guide.
+       * testsuite/std/ranges/iota/iota_view.cc: Augment test.
+
 2020-02-20  Jonathan Wakely  <jwak...@redhat.com>
 
        * include/bits/range_access.h (ranges::begin): Reject array of
diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
index 7a66491f2e4..6358ce86f79 100644
--- a/libstdc++-v3/include/std/ranges
+++ b/libstdc++-v3/include/std/ranges
@@ -635,6 +635,8 @@ namespace ranges
     class iota_view : public view_interface<iota_view<_Winc, _Bound>>
     {
     private:
+      struct _Sentinel;
+
       struct _Iterator
       {
       private:
@@ -811,11 +813,17 @@ namespace ranges
 
       private:
        _Winc _M_value = _Winc();
+
+        friend _Sentinel;
       };
 
       struct _Sentinel
       {
       private:
+       constexpr bool
+       _M_equal(const _Iterator& __x) const
+       { return __x._M_value == _M_bound; }
+
        _Bound _M_bound = _Bound();
 
       public:
@@ -827,7 +835,7 @@ namespace ranges
 
        friend constexpr bool
        operator==(const _Iterator& __x, const _Sentinel& __y)
-       { return __x._M_value == __y._M_bound; }
+       { return __y._M_equal(__x); }
 
        friend constexpr iter_difference_t<_Winc>
        operator-(const _Iterator& __x, const _Sentinel& __y)
@@ -933,7 +941,7 @@ namespace views
     template<typename _Tp, typename _Up>
       constexpr auto
       operator()(_Tp&& __e, _Up&& __f) const
-      { return iota_view{std::forward<_Tp>(__e), std::forward<_Tp>(__f)}; }
+      { return iota_view{std::forward<_Tp>(__e), std::forward<_Up>(__f)}; }
   };
 
   inline constexpr _Iota iota{};
diff --git a/libstdc++-v3/testsuite/std/ranges/access/ssize.cc 
b/libstdc++-v3/testsuite/std/ranges/access/ssize.cc
index 6f5478e2bb1..8423654c5f7 100644
--- a/libstdc++-v3/testsuite/std/ranges/access/ssize.cc
+++ b/libstdc++-v3/testsuite/std/ranges/access/ssize.cc
@@ -75,7 +75,7 @@ test05()
 void
 test06()
 {
-  auto i = std::views::iota(1ull, 5);
+  auto i = std::views::iota(1ull, 5u);
   auto s = std::ranges::ssize(i);
   using R = std::ranges::range_difference_t<decltype(i)>;
   static_assert( std::same_as<decltype(s), R> );
diff --git a/libstdc++-v3/testsuite/std/ranges/iota/iota_view.cc 
b/libstdc++-v3/testsuite/std/ranges/iota/iota_view.cc
index 798e745d3f0..65d166fbd3b 100644
--- a/libstdc++-v3/testsuite/std/ranges/iota/iota_view.cc
+++ b/libstdc++-v3/testsuite/std/ranges/iota/iota_view.cc
@@ -61,10 +61,27 @@ test03()
   VERIFY( it == v.end() );
 }
 
+void
+test04()
+{
+  int x[] = {1,2,3};
+  auto v = std::ranges::views::iota(std::counted_iterator(x, 3),
+                                   std::default_sentinel);
+  auto it = v.begin();
+  VERIFY( (*it).base() == x );
+  ++it;
+  VERIFY( (*it).base() == x+1 );
+  ++it;
+  VERIFY( (*it).base() == x+2 );
+  ++it;
+  VERIFY( it == v.end() );
+}
+
 int
 main()
 {
   test01();
   test02();
   test03();
+  test04();
 }
-- 
2.25.1.291.ge68e29171c

Reply via email to