libstdc++: Forward second argument of views::iota using the correct type
authorPatrick Palka <ppalka@redhat.com>
Thu, 20 Feb 2020 04:14:02 +0000 (23:14 -0500)
committerPatrick Palka <ppalka@redhat.com>
Thu, 20 Feb 2020 18:54:43 +0000 (13:54 -0500)
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
libstdc++-v3/include/std/ranges
libstdc++-v3/testsuite/std/ranges/access/ssize.cc
libstdc++-v3/testsuite/std/ranges/iota/iota_view.cc

index 30cf706..deade1c 100644 (file)
@@ -1,3 +1,15 @@
+2020-02-20  Patrick Palka  <ppalka@redhat.com>
+
+       * 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.
+
 2020-02-20  Jonathan Wakely  <jwakely@redhat.com>
 
        * include/bits/range_access.h (ranges::begin): Reject array of
index 7a66491..6358ce8 100644 (file)
@@ -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{};
index 6f5478e..8423654 100644 (file)
@@ -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> );
index 798e745..65d166f 100644 (file)
@@ -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();
 }