[libcxx-commits] [libcxx] 43bc1e5 - [libc++][ranges] Implement Ranges changes to `istream{, buf}_iterator`.

Konstantin Varlamov via libcxx-commits libcxx-commits at lists.llvm.org
Tue Feb 15 16:59:52 PST 2022


Author: Konstantin Varlamov
Date: 2022-02-15T16:59:42-08:00
New Revision: 43bc1e5600344d54ad87eae9b1515e2fa5a9597e

URL: https://github.com/llvm/llvm-project/commit/43bc1e5600344d54ad87eae9b1515e2fa5a9597e
DIFF: https://github.com/llvm/llvm-project/commit/43bc1e5600344d54ad87eae9b1515e2fa5a9597e.diff

LOG: [libc++][ranges] Implement Ranges changes to `istream{,buf}_iterator`.

The changes from the One Ranges Proposal amount to adding:
- a constructor that takes a `default_sentinel_t` and is equivalent to
  the default constructor;
- an `operator==` that compares the iterator to `default_sentinel_t`.

The original proposal defined two overloads for `operator==` (different
argument order) as well as `operator!=`. This has been removed by
[P1614](https://wg21.link/p1614).

Differential Revision: https://reviews.llvm.org/D119620

Added: 
    libcxx/test/std/iterators/stream.iterators/istream.iterator/istream.iterator.cons/default_sentinel_t.pass.cpp
    libcxx/test/std/iterators/stream.iterators/istreambuf.iterator/istreambuf.iterator.cons/default_sentinel_t.pass.cpp

Modified: 
    libcxx/docs/Status/RangesPaper.csv
    libcxx/include/__iterator/default_sentinel.h
    libcxx/include/__iterator/istream_iterator.h
    libcxx/include/__iterator/istreambuf_iterator.h
    libcxx/include/iterator
    libcxx/test/std/iterators/stream.iterators/istream.iterator/istream.iterator.cons/default.pass.cpp
    libcxx/test/std/iterators/stream.iterators/istream.iterator/istream.iterator.ops/equal.pass.cpp
    libcxx/test/std/iterators/stream.iterators/istreambuf.iterator/istreambuf.iterator.cons/default.pass.cpp
    libcxx/test/std/iterators/stream.iterators/istreambuf.iterator/istreambuf.iterator_op!=/not_equal.pass.cpp
    libcxx/test/std/iterators/stream.iterators/istreambuf.iterator/istreambuf.iterator_op==/equal.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/Status/RangesPaper.csv b/libcxx/docs/Status/RangesPaper.csv
index 0aa3504ca083e..3e7be37614ad1 100644
--- a/libcxx/docs/Status/RangesPaper.csv
+++ b/libcxx/docs/Status/RangesPaper.csv
@@ -91,11 +91,11 @@ Section,Description,Dependencies,Assignee,Complete
 | [iterator.cust.move]
 | [default.sentinels]",Zoe Carver,✅
 `[stream.iterators] <https://wg21.link/stream.iterators>`_,"
-| Updates to istream_iterator
+| `Updates to istream_iterator <https://llvm.org/D119620>`_
 | `Updates to ostream_iterator <https://llvm.org/D103273>`_
-| Updates to istreambuf_iterator
+| `Updates to istreambuf_iterator <https://llvm.org/D119620>`_
 | `Updates to ostreambuf_iterator <https://llvm.org/D103273>`_
-",[default.sentinels],Various,In progress
+",[default.sentinels],Various,✅
 `[range.access] <https://wg21.link/range.access>`_,"| `ranges::begin <https://llvm.org/D100255>`_
 | `ranges::end <https://llvm.org/D100255>`_
 | `range::cbegin <https://llvm.org/D100255>`_

diff  --git a/libcxx/include/__iterator/default_sentinel.h b/libcxx/include/__iterator/default_sentinel.h
index 0864d1c7443cb..669032aa97297 100644
--- a/libcxx/include/__iterator/default_sentinel.h
+++ b/libcxx/include/__iterator/default_sentinel.h
@@ -18,12 +18,12 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
-#if !defined(_LIBCPP_HAS_NO_CONCEPTS)
+#if _LIBCPP_STD_VER > 17
 
 struct default_sentinel_t { };
 inline constexpr default_sentinel_t default_sentinel{};
 
-#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
+#endif // _LIBCPP_STD_VER > 17
 
 _LIBCPP_END_NAMESPACE_STD
 

diff  --git a/libcxx/include/__iterator/istream_iterator.h b/libcxx/include/__iterator/istream_iterator.h
index f7014b8af1479..9ee0a989b8f6b 100644
--- a/libcxx/include/__iterator/istream_iterator.h
+++ b/libcxx/include/__iterator/istream_iterator.h
@@ -11,6 +11,7 @@
 #define _LIBCPP___ITERATOR_ISTREAM_ITERATOR_H
 
 #include <__config>
+#include <__iterator/default_sentinel.h>
 #include <__iterator/iterator.h>
 #include <__iterator/iterator_traits.h>
 #include <__memory/addressof.h>
@@ -45,6 +46,9 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP
     _Tp __value_;
 public:
     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR istream_iterator() : __in_stream_(nullptr), __value_() {}
+#if _LIBCPP_STD_VER > 17
+    _LIBCPP_HIDE_FROM_ABI constexpr istream_iterator(default_sentinel_t) : istream_iterator() {}
+#endif // _LIBCPP_STD_VER > 17
     _LIBCPP_INLINE_VISIBILITY istream_iterator(istream_type& __s) : __in_stream_(_VSTD::addressof(__s))
         {
             if (!(*__in_stream_ >> __value_))
@@ -67,6 +71,12 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP
     bool
     operator==(const istream_iterator<_Up, _CharU, _TraitsU, _DistanceU>& __x,
                const istream_iterator<_Up, _CharU, _TraitsU, _DistanceU>& __y);
+
+#if _LIBCPP_STD_VER > 17
+    friend _LIBCPP_HIDE_FROM_ABI bool operator==(const istream_iterator& __i, default_sentinel_t) {
+      return __i.__in_stream_ == nullptr;
+    }
+#endif // _LIBCPP_STD_VER > 17
 };
 
 template <class _Tp, class _CharT, class _Traits, class _Distance>
@@ -78,6 +88,7 @@ operator==(const istream_iterator<_Tp, _CharT, _Traits, _Distance>& __x,
     return __x.__in_stream_ == __y.__in_stream_;
 }
 
+#if _LIBCPP_STD_VER <= 17
 template <class _Tp, class _CharT, class _Traits, class _Distance>
 inline _LIBCPP_INLINE_VISIBILITY
 bool
@@ -86,6 +97,7 @@ operator!=(const istream_iterator<_Tp, _CharT, _Traits, _Distance>& __x,
 {
     return !(__x == __y);
 }
+#endif // _LIBCPP_STD_VER <= 17
 
 _LIBCPP_END_NAMESPACE_STD
 

diff  --git a/libcxx/include/__iterator/istreambuf_iterator.h b/libcxx/include/__iterator/istreambuf_iterator.h
index 16b2cb7b4a85b..3b16f79476783 100644
--- a/libcxx/include/__iterator/istreambuf_iterator.h
+++ b/libcxx/include/__iterator/istreambuf_iterator.h
@@ -11,6 +11,7 @@
 #define _LIBCPP___ITERATOR_ISTREAMBUF_ITERATOR_H
 
 #include <__config>
+#include <__iterator/default_sentinel.h>
 #include <__iterator/iterator.h>
 #include <__iterator/iterator_traits.h>
 #include <iosfwd> // for forward declaration of basic_streambuf
@@ -65,6 +66,10 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP
     }
 public:
     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR istreambuf_iterator() _NOEXCEPT : __sbuf_(nullptr) {}
+#if _LIBCPP_STD_VER > 17
+    _LIBCPP_INLINE_VISIBILITY constexpr istreambuf_iterator(default_sentinel_t) noexcept
+        : istreambuf_iterator() {}
+#endif // _LIBCPP_STD_VER > 17
     _LIBCPP_INLINE_VISIBILITY istreambuf_iterator(istream_type& __s) _NOEXCEPT
         : __sbuf_(__s.rdbuf()) {}
     _LIBCPP_INLINE_VISIBILITY istreambuf_iterator(streambuf_type* __s) _NOEXCEPT
@@ -86,6 +91,12 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP
 
     _LIBCPP_INLINE_VISIBILITY bool equal(const istreambuf_iterator& __b) const
         {return __test_for_eof() == __b.__test_for_eof();}
+
+#if _LIBCPP_STD_VER > 17
+    friend _LIBCPP_HIDE_FROM_ABI bool operator==(const istreambuf_iterator& __i, default_sentinel_t) {
+      return __i.__test_for_eof();
+    }
+#endif // _LIBCPP_STD_VER > 17
 };
 
 template <class _CharT, class _Traits>
@@ -94,11 +105,13 @@ bool operator==(const istreambuf_iterator<_CharT,_Traits>& __a,
                 const istreambuf_iterator<_CharT,_Traits>& __b)
                 {return __a.equal(__b);}
 
+#if _LIBCPP_STD_VER <= 17
 template <class _CharT, class _Traits>
 inline _LIBCPP_INLINE_VISIBILITY
 bool operator!=(const istreambuf_iterator<_CharT,_Traits>& __a,
                 const istreambuf_iterator<_CharT,_Traits>& __b)
                 {return !__a.equal(__b);}
+#endif // _LIBCPP_STD_VER <= 17
 
 _LIBCPP_END_NAMESPACE_STD
 

diff  --git a/libcxx/include/iterator b/libcxx/include/iterator
index 202667809dcaf..fe91d15e6bc31 100644
--- a/libcxx/include/iterator
+++ b/libcxx/include/iterator
@@ -448,7 +448,8 @@ public:
     typedef traits                       traits_type;
     typedef basic_istream<charT, traits> istream_type;
 
-    constexpr istream_iterator();
+    istream_iterator(); // constexpr since C++11
+    constexpr istream_iterator(default_sentinel_t); // since C++20
     istream_iterator(istream_type& s);
     istream_iterator(const istream_iterator& x);
     ~istream_iterator();
@@ -457,6 +458,7 @@ public:
     const T* operator->() const;
     istream_iterator& operator++();
     istream_iterator  operator++(int);
+    friend bool operator==(const istream_iterator& i, default_sentinel_t); // since C++20
 };
 
 template <class T, class charT, class traits, class Distance>
@@ -464,7 +466,7 @@ bool operator==(const istream_iterator<T,charT,traits,Distance>& x,
                 const istream_iterator<T,charT,traits,Distance>& y);
 template <class T, class charT, class traits, class Distance>
 bool operator!=(const istream_iterator<T,charT,traits,Distance>& x,
-                const istream_iterator<T,charT,traits,Distance>& y);
+                const istream_iterator<T,charT,traits,Distance>& y); // until C++20
 
 template <class T, class charT = char, class traits = char_traits<charT> >
 class ostream_iterator
@@ -510,7 +512,8 @@ public:
     typedef basic_streambuf<charT, traits>  streambuf_type;
     typedef basic_istream<charT, traits>    istream_type;
 
-    istreambuf_iterator() noexcept;
+    istreambuf_iterator() noexcept; // constexpr since C++11
+    constexpr istreambuf_iterator(default_sentinel_t) noexcept; // since C++20
     istreambuf_iterator(istream_type& s) noexcept;
     istreambuf_iterator(streambuf_type* s) noexcept;
     istreambuf_iterator(a-private-type) noexcept;
@@ -521,6 +524,7 @@ public:
     a-private-type       operator++(int);
 
     bool equal(const istreambuf_iterator& b) const;
+    friend bool operator==(const istreambuf_iterator& i, default_sentinel_t s); // since C++20
 };
 
 template <class charT, class traits>
@@ -528,7 +532,7 @@ bool operator==(const istreambuf_iterator<charT,traits>& a,
                 const istreambuf_iterator<charT,traits>& b);
 template <class charT, class traits>
 bool operator!=(const istreambuf_iterator<charT,traits>& a,
-                const istreambuf_iterator<charT,traits>& b);
+                const istreambuf_iterator<charT,traits>& b); // until C++20
 
 template <class charT, class traits = char_traits<charT> >
 class ostreambuf_iterator

diff  --git a/libcxx/test/std/iterators/stream.iterators/istream.iterator/istream.iterator.cons/default.pass.cpp b/libcxx/test/std/iterators/stream.iterators/istream.iterator/istream.iterator.cons/default.pass.cpp
index 39ace08c88d34..7273223a7dbc1 100644
--- a/libcxx/test/std/iterators/stream.iterators/istream.iterator/istream.iterator.cons/default.pass.cpp
+++ b/libcxx/test/std/iterators/stream.iterators/istream.iterator/istream.iterator.cons/default.pass.cpp
@@ -10,7 +10,7 @@
 
 // class istream_iterator
 
-// constexpr istream_iterator();
+// istream_iterator(); // constexpr since C++11
 // C++17 says: If is_trivially_default_constructible_v<T> is true, then this
 //    constructor is a constexpr constructor.
 
@@ -38,8 +38,7 @@ void operator ()() const {}
 #endif
 
 
-int main(int, char**)
-{
+int main(int, char**) {
     {
     typedef std::istream_iterator<int> T;
     T it;

diff  --git a/libcxx/test/std/iterators/stream.iterators/istream.iterator/istream.iterator.cons/default_sentinel_t.pass.cpp b/libcxx/test/std/iterators/stream.iterators/istream.iterator/istream.iterator.cons/default_sentinel_t.pass.cpp
new file mode 100644
index 0000000000000..e1fc85ddd4f12
--- /dev/null
+++ b/libcxx/test/std/iterators/stream.iterators/istream.iterator/istream.iterator.cons/default_sentinel_t.pass.cpp
@@ -0,0 +1,37 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// <iterator>
+//
+// constexpr istream_iterator(default_sentinel_t); // since C++20
+
+#include <iterator>
+#include <cassert>
+
+int main(int, char**) {
+  using T = std::istream_iterator<int>;
+
+  {
+    T it(std::default_sentinel);
+    assert(it == T());
+  }
+
+  {
+    T it = std::default_sentinel;
+    assert(it == T());
+  }
+
+  {
+    constexpr T it(std::default_sentinel);
+    (void)it;
+  }
+
+  return 0;
+}

diff  --git a/libcxx/test/std/iterators/stream.iterators/istream.iterator/istream.iterator.ops/equal.pass.cpp b/libcxx/test/std/iterators/stream.iterators/istream.iterator/istream.iterator.ops/equal.pass.cpp
index 373d5ed0170c1..6ca6ce6b7215c 100644
--- a/libcxx/test/std/iterators/stream.iterators/istream.iterator/istream.iterator.ops/equal.pass.cpp
+++ b/libcxx/test/std/iterators/stream.iterators/istream.iterator/istream.iterator.ops/equal.pass.cpp
@@ -17,6 +17,8 @@
 // template <class T, class charT, class traits, class Distance>
 //   bool operator!=(const istream_iterator<T,charT,traits,Distance> &x,
 //                   const istream_iterator<T,charT,traits,Distance> &y);
+//
+// friend bool operator==(const istream_iterator& i, default_sentinel_t); // since C++20
 
 #include <iterator>
 #include <sstream>
@@ -24,8 +26,8 @@
 
 #include "test_macros.h"
 
-int main(int, char**)
-{
+int main(int, char**) {
+  {
     std::istringstream inf1(" 1 23");
     std::istringstream inf2(" 1 23");
     std::istream_iterator<int> i1(inf1);
@@ -52,7 +54,35 @@ int main(int, char**)
     assert(i4 == i5);
 
     assert(std::operator==(i1, i2));
+#if TEST_STD_VER <= 17
     assert(std::operator!=(i1, i3));
+#endif
+  }
+
+#if TEST_STD_VER > 17
+  {
+    std::istream_iterator<int> i1;
+    std::istream_iterator<int> i2(std::default_sentinel);
+    assert(i1 == i2);
+
+    assert(i1 == std::default_sentinel);
+    assert(i2 == std::default_sentinel);
+    assert(std::default_sentinel == i1);
+    assert(std::default_sentinel == i2);
+    assert(!(i1 != std::default_sentinel));
+    assert(!(i2 != std::default_sentinel));
+    assert(!(std::default_sentinel != i1));
+    assert(!(std::default_sentinel != i2));
+
+    std::istringstream stream(" 1 23");
+    std::istream_iterator<int> i3(stream);
+
+    assert(!(i3 == std::default_sentinel));
+    assert(!(std::default_sentinel == i3));
+    assert(i3 != std::default_sentinel);
+    assert(std::default_sentinel != i3);
+  }
+#endif
 
   return 0;
 }

diff  --git a/libcxx/test/std/iterators/stream.iterators/istreambuf.iterator/istreambuf.iterator.cons/default.pass.cpp b/libcxx/test/std/iterators/stream.iterators/istreambuf.iterator/istreambuf.iterator.cons/default.pass.cpp
index ccda358407a8f..1e8baeae105dd 100644
--- a/libcxx/test/std/iterators/stream.iterators/istreambuf.iterator/istreambuf.iterator.cons/default.pass.cpp
+++ b/libcxx/test/std/iterators/stream.iterators/istreambuf.iterator/istreambuf.iterator.cons/default.pass.cpp
@@ -10,7 +10,7 @@
 
 // istreambuf_iterator
 //
-// istreambuf_iterator() throw();
+// istreambuf_iterator() noexcept; // constexpr since C++11
 //
 // All specializations of istreambuf_iterator shall have a trivial copy constructor,
 //    a constexpr default constructor and a trivial destructor.
@@ -21,28 +21,31 @@
 
 #include "test_macros.h"
 
-int main(int, char**)
-{
-    {
-        typedef std::istreambuf_iterator<char> T;
-        T it;
-        assert(it == T());
+int main(int, char**) {
+  {
+    typedef std::istreambuf_iterator<char> T;
+    T it;
+    assert(it == T());
 #if TEST_STD_VER >= 11
-        constexpr T it2;
-        (void)it2;
+    constexpr T it2;
+    (void)it2;
 #endif
-    }
+
+    ASSERT_NOEXCEPT(T());
+  }
 
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
-    {
-        typedef std::istreambuf_iterator<wchar_t> T;
-        T it;
-        assert(it == T());
+  {
+    typedef std::istreambuf_iterator<wchar_t> T;
+    T it;
+    assert(it == T());
 #if TEST_STD_VER >= 11
-        constexpr T it2;
-        (void)it2;
+    constexpr T it2;
+    (void)it2;
 #endif
-    }
+
+    ASSERT_NOEXCEPT(T());
+  }
 #endif // TEST_HAS_NO_WIDE_CHARACTERS
 
   return 0;

diff  --git a/libcxx/test/std/iterators/stream.iterators/istreambuf.iterator/istreambuf.iterator.cons/default_sentinel_t.pass.cpp b/libcxx/test/std/iterators/stream.iterators/istreambuf.iterator/istreambuf.iterator.cons/default_sentinel_t.pass.cpp
new file mode 100644
index 0000000000000..b2e6dfe7a4e5b
--- /dev/null
+++ b/libcxx/test/std/iterators/stream.iterators/istreambuf.iterator/istreambuf.iterator.cons/default_sentinel_t.pass.cpp
@@ -0,0 +1,42 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// <iterator>
+
+// constexpr istreambuf_iterator(default_sentinel_t) noexcept; // since C++20
+
+#include <iterator>
+#include <sstream>
+#include <cassert>
+
+#include "test_macros.h"
+
+int main(int, char**) {
+  using T = std::istreambuf_iterator<char>;
+
+  {
+    T it(std::default_sentinel);
+    assert(it == T());
+  }
+
+  {
+    T it = std::default_sentinel;
+    assert(it == T());
+  }
+
+  {
+    constexpr T it(std::default_sentinel);
+    (void)it;
+  }
+
+  ASSERT_NOEXCEPT(T(std::default_sentinel));
+
+  return 0;
+}

diff  --git a/libcxx/test/std/iterators/stream.iterators/istreambuf.iterator/istreambuf.iterator_op!=/not_equal.pass.cpp b/libcxx/test/std/iterators/stream.iterators/istreambuf.iterator/istreambuf.iterator_op!=/not_equal.pass.cpp
index 2771911bbae50..80520e579564f 100644
--- a/libcxx/test/std/iterators/stream.iterators/istreambuf.iterator/istreambuf.iterator_op!=/not_equal.pass.cpp
+++ b/libcxx/test/std/iterators/stream.iterators/istreambuf.iterator/istreambuf.iterator_op!=/not_equal.pass.cpp
@@ -20,87 +20,106 @@
 
 #include "test_macros.h"
 
-int main(int, char**)
-{
-    {
-        std::istringstream inf1("abc");
-        std::istringstream inf2("def");
-        std::istreambuf_iterator<char> i1(inf1);
-        std::istreambuf_iterator<char> i2(inf2);
-        std::istreambuf_iterator<char> i3;
-        std::istreambuf_iterator<char> i4;
-        std::istreambuf_iterator<char> i5(nullptr);
-
-        assert(!(i1 != i1));
-        assert(!(i1 != i2));
-        assert( (i1 != i3));
-        assert( (i1 != i4));
-        assert( (i1 != i5));
-
-        assert(!(i2 != i1));
-        assert(!(i2 != i2));
-        assert( (i2 != i3));
-        assert( (i2 != i4));
-        assert( (i2 != i5));
-
-        assert( (i3 != i1));
-        assert( (i3 != i2));
-        assert(!(i3 != i3));
-        assert(!(i3 != i4));
-        assert(!(i3 != i5));
-
-        assert( (i4 != i1));
-        assert( (i4 != i2));
-        assert(!(i4 != i3));
-        assert(!(i4 != i4));
-        assert(!(i4 != i5));
-
-        assert( (i5 != i1));
-        assert( (i5 != i2));
-        assert(!(i5 != i3));
-        assert(!(i5 != i4));
-        assert(!(i5 != i5));
-    }
+int main(int, char**) {
+  {
+    std::istringstream inf1("abc");
+    std::istringstream inf2("def");
+    std::istreambuf_iterator<char> i1(inf1);
+    std::istreambuf_iterator<char> i2(inf2);
+    std::istreambuf_iterator<char> i3;
+    std::istreambuf_iterator<char> i4;
+    std::istreambuf_iterator<char> i5(nullptr);
+
+    assert(!(i1 != i1));
+    assert(!(i1 != i2));
+    assert( (i1 != i3));
+    assert( (i1 != i4));
+    assert( (i1 != i5));
+
+    assert(!(i2 != i1));
+    assert(!(i2 != i2));
+    assert( (i2 != i3));
+    assert( (i2 != i4));
+    assert( (i2 != i5));
+
+    assert( (i3 != i1));
+    assert( (i3 != i2));
+    assert(!(i3 != i3));
+    assert(!(i3 != i4));
+    assert(!(i3 != i5));
+
+    assert( (i4 != i1));
+    assert( (i4 != i2));
+    assert(!(i4 != i3));
+    assert(!(i4 != i4));
+    assert(!(i4 != i5));
+
+    assert( (i5 != i1));
+    assert( (i5 != i2));
+    assert(!(i5 != i3));
+    assert(!(i5 != i4));
+    assert(!(i5 != i5));
+  }
+
+#if TEST_STD_VER > 17
+  {
+    std::istreambuf_iterator<char> i1;
+    std::istreambuf_iterator<char> i2(std::default_sentinel);
+    assert(i1 == i2);
+
+    assert(!(i1 != std::default_sentinel));
+    assert(!(i2 != std::default_sentinel));
+    assert(!(std::default_sentinel != i1));
+    assert(!(std::default_sentinel != i2));
+
+    std::istringstream stream(" 1 23");
+    std::istreambuf_iterator<char> i3(stream);
+
+    assert(i3 != std::default_sentinel);
+    assert(std::default_sentinel != i3);
+  }
+#endif
+
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
-    {
-        std::wistringstream inf1(L"abc");
-        std::wistringstream inf2(L"def");
-        std::istreambuf_iterator<wchar_t> i1(inf1);
-        std::istreambuf_iterator<wchar_t> i2(inf2);
-        std::istreambuf_iterator<wchar_t> i3;
-        std::istreambuf_iterator<wchar_t> i4;
-        std::istreambuf_iterator<wchar_t> i5(nullptr);
-
-        assert(!(i1 != i1));
-        assert(!(i1 != i2));
-        assert( (i1 != i3));
-        assert( (i1 != i4));
-        assert( (i1 != i5));
-
-        assert(!(i2 != i1));
-        assert(!(i2 != i2));
-        assert( (i2 != i3));
-        assert( (i2 != i4));
-        assert( (i2 != i5));
-
-        assert( (i3 != i1));
-        assert( (i3 != i2));
-        assert(!(i3 != i3));
-        assert(!(i3 != i4));
-        assert(!(i3 != i5));
-
-        assert( (i4 != i1));
-        assert( (i4 != i2));
-        assert(!(i4 != i3));
-        assert(!(i4 != i4));
-        assert(!(i4 != i5));
-
-        assert( (i5 != i1));
-        assert( (i5 != i2));
-        assert(!(i5 != i3));
-        assert(!(i5 != i4));
-        assert(!(i5 != i5));
-    }
+  {
+    std::wistringstream inf1(L"abc");
+    std::wistringstream inf2(L"def");
+    std::istreambuf_iterator<wchar_t> i1(inf1);
+    std::istreambuf_iterator<wchar_t> i2(inf2);
+    std::istreambuf_iterator<wchar_t> i3;
+    std::istreambuf_iterator<wchar_t> i4;
+    std::istreambuf_iterator<wchar_t> i5(nullptr);
+
+    assert(!(i1 != i1));
+    assert(!(i1 != i2));
+    assert( (i1 != i3));
+    assert( (i1 != i4));
+    assert( (i1 != i5));
+
+    assert(!(i2 != i1));
+    assert(!(i2 != i2));
+    assert( (i2 != i3));
+    assert( (i2 != i4));
+    assert( (i2 != i5));
+
+    assert( (i3 != i1));
+    assert( (i3 != i2));
+    assert(!(i3 != i3));
+    assert(!(i3 != i4));
+    assert(!(i3 != i5));
+
+    assert( (i4 != i1));
+    assert( (i4 != i2));
+    assert(!(i4 != i3));
+    assert(!(i4 != i4));
+    assert(!(i4 != i5));
+
+    assert( (i5 != i1));
+    assert( (i5 != i2));
+    assert(!(i5 != i3));
+    assert(!(i5 != i4));
+    assert(!(i5 != i5));
+  }
 #endif // TEST_HAS_NO_WIDE_CHARACTERS
 
   return 0;

diff  --git a/libcxx/test/std/iterators/stream.iterators/istreambuf.iterator/istreambuf.iterator_op==/equal.pass.cpp b/libcxx/test/std/iterators/stream.iterators/istreambuf.iterator/istreambuf.iterator_op==/equal.pass.cpp
index c0fbf687ef4fb..e0dda2e4c8ab7 100644
--- a/libcxx/test/std/iterators/stream.iterators/istreambuf.iterator/istreambuf.iterator_op==/equal.pass.cpp
+++ b/libcxx/test/std/iterators/stream.iterators/istreambuf.iterator/istreambuf.iterator_op==/equal.pass.cpp
@@ -13,6 +13,8 @@
 // template <class charT, class traits>
 //   bool operator==(const istreambuf_iterator<charT,traits>& a,
 //                   const istreambuf_iterator<charT,traits>& b);
+//
+// friend bool operator==(const istreambuf_iterator& i, default_sentinel_t s); // since C++20
 
 #include <iterator>
 #include <sstream>
@@ -20,87 +22,106 @@
 
 #include "test_macros.h"
 
-int main(int, char**)
-{
-    {
-        std::istringstream inf1("abc");
-        std::istringstream inf2("def");
-        std::istreambuf_iterator<char> i1(inf1);
-        std::istreambuf_iterator<char> i2(inf2);
-        std::istreambuf_iterator<char> i3;
-        std::istreambuf_iterator<char> i4;
-        std::istreambuf_iterator<char> i5(nullptr);
-
-        assert( (i1 == i1));
-        assert( (i1 == i2));
-        assert(!(i1 == i3));
-        assert(!(i1 == i4));
-        assert(!(i1 == i5));
-
-        assert( (i2 == i1));
-        assert( (i2 == i2));
-        assert(!(i2 == i3));
-        assert(!(i2 == i4));
-        assert(!(i2 == i5));
-
-        assert(!(i3 == i1));
-        assert(!(i3 == i2));
-        assert( (i3 == i3));
-        assert( (i3 == i4));
-        assert( (i3 == i5));
-
-        assert(!(i4 == i1));
-        assert(!(i4 == i2));
-        assert( (i4 == i3));
-        assert( (i4 == i4));
-        assert( (i4 == i5));
-
-        assert(!(i5 == i1));
-        assert(!(i5 == i2));
-        assert( (i5 == i3));
-        assert( (i5 == i4));
-        assert( (i5 == i5));
-    }
+int main(int, char**) {
+  {
+    std::istringstream inf1("abc");
+    std::istringstream inf2("def");
+    std::istreambuf_iterator<char> i1(inf1);
+    std::istreambuf_iterator<char> i2(inf2);
+    std::istreambuf_iterator<char> i3;
+    std::istreambuf_iterator<char> i4;
+    std::istreambuf_iterator<char> i5(nullptr);
+
+    assert( (i1 == i1));
+    assert( (i1 == i2));
+    assert(!(i1 == i3));
+    assert(!(i1 == i4));
+    assert(!(i1 == i5));
+
+    assert( (i2 == i1));
+    assert( (i2 == i2));
+    assert(!(i2 == i3));
+    assert(!(i2 == i4));
+    assert(!(i2 == i5));
+
+    assert(!(i3 == i1));
+    assert(!(i3 == i2));
+    assert( (i3 == i3));
+    assert( (i3 == i4));
+    assert( (i3 == i5));
+
+    assert(!(i4 == i1));
+    assert(!(i4 == i2));
+    assert( (i4 == i3));
+    assert( (i4 == i4));
+    assert( (i4 == i5));
+
+    assert(!(i5 == i1));
+    assert(!(i5 == i2));
+    assert( (i5 == i3));
+    assert( (i5 == i4));
+    assert( (i5 == i5));
+  }
+
+#if TEST_STD_VER > 17
+  {
+    std::istreambuf_iterator<char> i1;
+    std::istreambuf_iterator<char> i2(std::default_sentinel);
+    assert(i1 == i2);
+
+    assert(i1 == std::default_sentinel);
+    assert(i2 == std::default_sentinel);
+    assert(std::default_sentinel == i1);
+    assert(std::default_sentinel == i2);
+
+    std::istringstream stream(" 1 23");
+    std::istreambuf_iterator<char> i3(stream);
+
+    assert(!(i3 == std::default_sentinel));
+    assert(!(std::default_sentinel == i3));
+  }
+#endif
+
 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
-    {
-        std::wistringstream inf1(L"abc");
-        std::wistringstream inf2(L"def");
-        std::istreambuf_iterator<wchar_t> i1(inf1);
-        std::istreambuf_iterator<wchar_t> i2(inf2);
-        std::istreambuf_iterator<wchar_t> i3;
-        std::istreambuf_iterator<wchar_t> i4;
-        std::istreambuf_iterator<wchar_t> i5(nullptr);
-
-        assert( (i1 == i1));
-        assert( (i1 == i2));
-        assert(!(i1 == i3));
-        assert(!(i1 == i4));
-        assert(!(i1 == i5));
-
-        assert( (i2 == i1));
-        assert( (i2 == i2));
-        assert(!(i2 == i3));
-        assert(!(i2 == i4));
-        assert(!(i2 == i5));
-
-        assert(!(i3 == i1));
-        assert(!(i3 == i2));
-        assert( (i3 == i3));
-        assert( (i3 == i4));
-        assert( (i3 == i5));
-
-        assert(!(i4 == i1));
-        assert(!(i4 == i2));
-        assert( (i4 == i3));
-        assert( (i4 == i4));
-        assert( (i4 == i5));
-
-        assert(!(i5 == i1));
-        assert(!(i5 == i2));
-        assert( (i5 == i3));
-        assert( (i5 == i4));
-        assert( (i5 == i5));
-    }
+  {
+    std::wistringstream inf1(L"abc");
+    std::wistringstream inf2(L"def");
+    std::istreambuf_iterator<wchar_t> i1(inf1);
+    std::istreambuf_iterator<wchar_t> i2(inf2);
+    std::istreambuf_iterator<wchar_t> i3;
+    std::istreambuf_iterator<wchar_t> i4;
+    std::istreambuf_iterator<wchar_t> i5(nullptr);
+
+    assert( (i1 == i1));
+    assert( (i1 == i2));
+    assert(!(i1 == i3));
+    assert(!(i1 == i4));
+    assert(!(i1 == i5));
+
+    assert( (i2 == i1));
+    assert( (i2 == i2));
+    assert(!(i2 == i3));
+    assert(!(i2 == i4));
+    assert(!(i2 == i5));
+
+    assert(!(i3 == i1));
+    assert(!(i3 == i2));
+    assert( (i3 == i3));
+    assert( (i3 == i4));
+    assert( (i3 == i5));
+
+    assert(!(i4 == i1));
+    assert(!(i4 == i2));
+    assert( (i4 == i3));
+    assert( (i4 == i4));
+    assert( (i4 == i5));
+
+    assert(!(i5 == i1));
+    assert(!(i5 == i2));
+    assert( (i5 == i3));
+    assert( (i5 == i4));
+    assert( (i5 == i5));
+  }
 #endif // TEST_HAS_NO_WIDE_CHARACTERS
 
   return 0;


        


More information about the libcxx-commits mailing list