]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Fix split_view::_OuterIter::operator++ [LWG 3505]
authorPatrick Palka <ppalka@redhat.com>
Thu, 8 Apr 2021 20:45:27 +0000 (16:45 -0400)
committerPatrick Palka <ppalka@redhat.com>
Thu, 8 Apr 2021 20:45:27 +0000 (16:45 -0400)
libstdc++-v3/ChangeLog:

* include/std/ranges (__detail::find): Define.
(split_view::_OuterIter::operator++): Apply proposed resolution
of LWG 3505.
* testsuite/std/ranges/adaptors/split.cc (test10): New test.

libstdc++-v3/include/std/ranges
libstdc++-v3/testsuite/std/ranges/adaptors/split.cc

index 9077271e4e6c70a3b2c3630d7155e22b1d01d1b3..baec8c0efefd1deeb00baad51cec2fff9f6b730d 100644 (file)
@@ -982,6 +982,16 @@ namespace views::__adaptor
   // having to include that entire header.
   namespace __detail
   {
+    template<typename _Iter, typename _Sent, typename _Tp>
+      constexpr _Iter
+      find(_Iter __first, _Sent __last, const _Tp& __value)
+      {
+       while (__first != __last
+              && !(bool)(*__first == __value))
+         ++__first;
+       return __first;
+      }
+
     template<typename _Iter, typename _Sent, typename _Pred>
       constexpr _Iter
       find_if(_Iter __first, _Sent __last, _Pred __pred)
@@ -2656,21 +2666,31 @@ namespace views::__adaptor
          constexpr _OuterIter&
          operator++()
          {
+           // _GLIBCXX_RESOLVE_LIB_DEFECTS
+           // 3505. split_view::outer-iterator::operator++ misspecified
            const auto __end = ranges::end(_M_parent->_M_base);
            if (__current() == __end)
              return *this;
            const auto [__pbegin, __pend] = subrange{_M_parent->_M_pattern};
            if (__pbegin == __pend)
              ++__current();
+           else if constexpr (__detail::__tiny_range<_Pattern>)
+             {
+               __current() = __detail::find(std::move(__current()), __end,
+                                            *__pbegin);
+               if (__current() != __end)
+                 ++__current();
+             }
            else
              do
                {
                  auto [__b, __p]
-                   = __detail::mismatch(std::move(__current()), __end,
-                                        __pbegin, __pend);
-                 __current() = std::move(__b);
+                   = __detail::mismatch(__current(), __end, __pbegin, __pend);
                  if (__p == __pend)
-                   break;
+                   {
+                     __current() = __b;
+                     break;
+                   }
                } while (++__current() != __end);
            return *this;
          }
index b9fb3728708adb2ff89f41775819d91bdfa7070c..9d2cfa8632aa8764605f9b2e9795638428a64cc7 100644 (file)
@@ -182,6 +182,17 @@ test09()
   static_assert(requires { adapt2(s); });
 }
 
+void
+test10()
+{
+  // LWG 3505
+  auto to_string = [] (auto r) {
+    return std::string(r.begin(), ranges::next(r.begin(), r.end()));
+  };
+  auto v = "xxyx"sv | views::split("xy"sv) | views::transform(to_string);
+  VERIFY( ranges::equal(v, (std::string_view[]){"x", "x"}) );
+}
+
 int
 main()
 {
@@ -194,4 +205,5 @@ main()
   test07();
   test08();
   test09();
+  test10();
 }