Skip to content

Commit 43bc1e5

Browse files
committed
[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
1 parent 8ee83ff commit 43bc1e5

File tree

12 files changed

+371
-191
lines changed

12 files changed

+371
-191
lines changed

libcxx/docs/Status/RangesPaper.csv

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,11 @@ Section,Description,Dependencies,Assignee,Complete
9191
| [iterator.cust.move]
9292
| [default.sentinels]",Zoe Carver,✅
9393
`[stream.iterators] <https://wg21.link/stream.iterators>`_,"
94-
| Updates to istream_iterator
94+
| `Updates to istream_iterator <https://llvm.org/D119620>`_
9595
| `Updates to ostream_iterator <https://llvm.org/D103273>`_
96-
| Updates to istreambuf_iterator
96+
| `Updates to istreambuf_iterator <https://llvm.org/D119620>`_
9797
| `Updates to ostreambuf_iterator <https://llvm.org/D103273>`_
98-
",[default.sentinels],Various,In progress
98+
",[default.sentinels],Various,
9999
`[range.access] <https://wg21.link/range.access>`_,"| `ranges::begin <https://llvm.org/D100255>`_
100100
| `ranges::end <https://llvm.org/D100255>`_
101101
| `range::cbegin <https://llvm.org/D100255>`_

libcxx/include/__iterator/default_sentinel.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@
1818

1919
_LIBCPP_BEGIN_NAMESPACE_STD
2020

21-
#if !defined(_LIBCPP_HAS_NO_CONCEPTS)
21+
#if _LIBCPP_STD_VER > 17
2222

2323
struct default_sentinel_t { };
2424
inline constexpr default_sentinel_t default_sentinel{};
2525

26-
#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
26+
#endif // _LIBCPP_STD_VER > 17
2727

2828
_LIBCPP_END_NAMESPACE_STD
2929

libcxx/include/__iterator/istream_iterator.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#define _LIBCPP___ITERATOR_ISTREAM_ITERATOR_H
1212

1313
#include <__config>
14+
#include <__iterator/default_sentinel.h>
1415
#include <__iterator/iterator.h>
1516
#include <__iterator/iterator_traits.h>
1617
#include <__memory/addressof.h>
@@ -45,6 +46,9 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP
4546
_Tp __value_;
4647
public:
4748
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR istream_iterator() : __in_stream_(nullptr), __value_() {}
49+
#if _LIBCPP_STD_VER > 17
50+
_LIBCPP_HIDE_FROM_ABI constexpr istream_iterator(default_sentinel_t) : istream_iterator() {}
51+
#endif // _LIBCPP_STD_VER > 17
4852
_LIBCPP_INLINE_VISIBILITY istream_iterator(istream_type& __s) : __in_stream_(_VSTD::addressof(__s))
4953
{
5054
if (!(*__in_stream_ >> __value_))
@@ -67,6 +71,12 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP
6771
bool
6872
operator==(const istream_iterator<_Up, _CharU, _TraitsU, _DistanceU>& __x,
6973
const istream_iterator<_Up, _CharU, _TraitsU, _DistanceU>& __y);
74+
75+
#if _LIBCPP_STD_VER > 17
76+
friend _LIBCPP_HIDE_FROM_ABI bool operator==(const istream_iterator& __i, default_sentinel_t) {
77+
return __i.__in_stream_ == nullptr;
78+
}
79+
#endif // _LIBCPP_STD_VER > 17
7080
};
7181

7282
template <class _Tp, class _CharT, class _Traits, class _Distance>
@@ -78,6 +88,7 @@ operator==(const istream_iterator<_Tp, _CharT, _Traits, _Distance>& __x,
7888
return __x.__in_stream_ == __y.__in_stream_;
7989
}
8090

91+
#if _LIBCPP_STD_VER <= 17
8192
template <class _Tp, class _CharT, class _Traits, class _Distance>
8293
inline _LIBCPP_INLINE_VISIBILITY
8394
bool
@@ -86,6 +97,7 @@ operator!=(const istream_iterator<_Tp, _CharT, _Traits, _Distance>& __x,
8697
{
8798
return !(__x == __y);
8899
}
100+
#endif // _LIBCPP_STD_VER <= 17
89101

90102
_LIBCPP_END_NAMESPACE_STD
91103

libcxx/include/__iterator/istreambuf_iterator.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#define _LIBCPP___ITERATOR_ISTREAMBUF_ITERATOR_H
1212

1313
#include <__config>
14+
#include <__iterator/default_sentinel.h>
1415
#include <__iterator/iterator.h>
1516
#include <__iterator/iterator_traits.h>
1617
#include <iosfwd> // for forward declaration of basic_streambuf
@@ -65,6 +66,10 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP
6566
}
6667
public:
6768
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR istreambuf_iterator() _NOEXCEPT : __sbuf_(nullptr) {}
69+
#if _LIBCPP_STD_VER > 17
70+
_LIBCPP_INLINE_VISIBILITY constexpr istreambuf_iterator(default_sentinel_t) noexcept
71+
: istreambuf_iterator() {}
72+
#endif // _LIBCPP_STD_VER > 17
6873
_LIBCPP_INLINE_VISIBILITY istreambuf_iterator(istream_type& __s) _NOEXCEPT
6974
: __sbuf_(__s.rdbuf()) {}
7075
_LIBCPP_INLINE_VISIBILITY istreambuf_iterator(streambuf_type* __s) _NOEXCEPT
@@ -86,6 +91,12 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP
8691

8792
_LIBCPP_INLINE_VISIBILITY bool equal(const istreambuf_iterator& __b) const
8893
{return __test_for_eof() == __b.__test_for_eof();}
94+
95+
#if _LIBCPP_STD_VER > 17
96+
friend _LIBCPP_HIDE_FROM_ABI bool operator==(const istreambuf_iterator& __i, default_sentinel_t) {
97+
return __i.__test_for_eof();
98+
}
99+
#endif // _LIBCPP_STD_VER > 17
89100
};
90101

91102
template <class _CharT, class _Traits>
@@ -94,11 +105,13 @@ bool operator==(const istreambuf_iterator<_CharT,_Traits>& __a,
94105
const istreambuf_iterator<_CharT,_Traits>& __b)
95106
{return __a.equal(__b);}
96107

108+
#if _LIBCPP_STD_VER <= 17
97109
template <class _CharT, class _Traits>
98110
inline _LIBCPP_INLINE_VISIBILITY
99111
bool operator!=(const istreambuf_iterator<_CharT,_Traits>& __a,
100112
const istreambuf_iterator<_CharT,_Traits>& __b)
101113
{return !__a.equal(__b);}
114+
#endif // _LIBCPP_STD_VER <= 17
102115

103116
_LIBCPP_END_NAMESPACE_STD
104117

libcxx/include/iterator

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,8 @@ public:
448448
typedef traits traits_type;
449449
typedef basic_istream<charT, traits> istream_type;
450450
451-
constexpr istream_iterator();
451+
istream_iterator(); // constexpr since C++11
452+
constexpr istream_iterator(default_sentinel_t); // since C++20
452453
istream_iterator(istream_type& s);
453454
istream_iterator(const istream_iterator& x);
454455
~istream_iterator();
@@ -457,14 +458,15 @@ public:
457458
const T* operator->() const;
458459
istream_iterator& operator++();
459460
istream_iterator operator++(int);
461+
friend bool operator==(const istream_iterator& i, default_sentinel_t); // since C++20
460462
};
461463
462464
template <class T, class charT, class traits, class Distance>
463465
bool operator==(const istream_iterator<T,charT,traits,Distance>& x,
464466
const istream_iterator<T,charT,traits,Distance>& y);
465467
template <class T, class charT, class traits, class Distance>
466468
bool operator!=(const istream_iterator<T,charT,traits,Distance>& x,
467-
const istream_iterator<T,charT,traits,Distance>& y);
469+
const istream_iterator<T,charT,traits,Distance>& y); // until C++20
468470
469471
template <class T, class charT = char, class traits = char_traits<charT> >
470472
class ostream_iterator
@@ -510,7 +512,8 @@ public:
510512
typedef basic_streambuf<charT, traits> streambuf_type;
511513
typedef basic_istream<charT, traits> istream_type;
512514
513-
istreambuf_iterator() noexcept;
515+
istreambuf_iterator() noexcept; // constexpr since C++11
516+
constexpr istreambuf_iterator(default_sentinel_t) noexcept; // since C++20
514517
istreambuf_iterator(istream_type& s) noexcept;
515518
istreambuf_iterator(streambuf_type* s) noexcept;
516519
istreambuf_iterator(a-private-type) noexcept;
@@ -521,14 +524,15 @@ public:
521524
a-private-type operator++(int);
522525
523526
bool equal(const istreambuf_iterator& b) const;
527+
friend bool operator==(const istreambuf_iterator& i, default_sentinel_t s); // since C++20
524528
};
525529
526530
template <class charT, class traits>
527531
bool operator==(const istreambuf_iterator<charT,traits>& a,
528532
const istreambuf_iterator<charT,traits>& b);
529533
template <class charT, class traits>
530534
bool operator!=(const istreambuf_iterator<charT,traits>& a,
531-
const istreambuf_iterator<charT,traits>& b);
535+
const istreambuf_iterator<charT,traits>& b); // until C++20
532536
533537
template <class charT, class traits = char_traits<charT> >
534538
class ostreambuf_iterator

libcxx/test/std/iterators/stream.iterators/istream.iterator/istream.iterator.cons/default.pass.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
// class istream_iterator
1212

13-
// constexpr istream_iterator();
13+
// istream_iterator(); // constexpr since C++11
1414
// C++17 says: If is_trivially_default_constructible_v<T> is true, then this
1515
// constructor is a constexpr constructor.
1616

@@ -38,8 +38,7 @@ void operator ()() const {}
3838
#endif
3939

4040

41-
int main(int, char**)
42-
{
41+
int main(int, char**) {
4342
{
4443
typedef std::istream_iterator<int> T;
4544
T it;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17
10+
11+
// <iterator>
12+
//
13+
// constexpr istream_iterator(default_sentinel_t); // since C++20
14+
15+
#include <iterator>
16+
#include <cassert>
17+
18+
int main(int, char**) {
19+
using T = std::istream_iterator<int>;
20+
21+
{
22+
T it(std::default_sentinel);
23+
assert(it == T());
24+
}
25+
26+
{
27+
T it = std::default_sentinel;
28+
assert(it == T());
29+
}
30+
31+
{
32+
constexpr T it(std::default_sentinel);
33+
(void)it;
34+
}
35+
36+
return 0;
37+
}

libcxx/test/std/iterators/stream.iterators/istream.iterator/istream.iterator.ops/equal.pass.cpp

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,17 @@
1717
// template <class T, class charT, class traits, class Distance>
1818
// bool operator!=(const istream_iterator<T,charT,traits,Distance> &x,
1919
// const istream_iterator<T,charT,traits,Distance> &y);
20+
//
21+
// friend bool operator==(const istream_iterator& i, default_sentinel_t); // since C++20
2022

2123
#include <iterator>
2224
#include <sstream>
2325
#include <cassert>
2426

2527
#include "test_macros.h"
2628

27-
int main(int, char**)
28-
{
29+
int main(int, char**) {
30+
{
2931
std::istringstream inf1(" 1 23");
3032
std::istringstream inf2(" 1 23");
3133
std::istream_iterator<int> i1(inf1);
@@ -52,7 +54,35 @@ int main(int, char**)
5254
assert(i4 == i5);
5355

5456
assert(std::operator==(i1, i2));
57+
#if TEST_STD_VER <= 17
5558
assert(std::operator!=(i1, i3));
59+
#endif
60+
}
61+
62+
#if TEST_STD_VER > 17
63+
{
64+
std::istream_iterator<int> i1;
65+
std::istream_iterator<int> i2(std::default_sentinel);
66+
assert(i1 == i2);
67+
68+
assert(i1 == std::default_sentinel);
69+
assert(i2 == std::default_sentinel);
70+
assert(std::default_sentinel == i1);
71+
assert(std::default_sentinel == i2);
72+
assert(!(i1 != std::default_sentinel));
73+
assert(!(i2 != std::default_sentinel));
74+
assert(!(std::default_sentinel != i1));
75+
assert(!(std::default_sentinel != i2));
76+
77+
std::istringstream stream(" 1 23");
78+
std::istream_iterator<int> i3(stream);
79+
80+
assert(!(i3 == std::default_sentinel));
81+
assert(!(std::default_sentinel == i3));
82+
assert(i3 != std::default_sentinel);
83+
assert(std::default_sentinel != i3);
84+
}
85+
#endif
5686

5787
return 0;
5888
}

libcxx/test/std/iterators/stream.iterators/istreambuf.iterator/istreambuf.iterator.cons/default.pass.cpp

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
// istreambuf_iterator
1212
//
13-
// istreambuf_iterator() throw();
13+
// istreambuf_iterator() noexcept; // constexpr since C++11
1414
//
1515
// All specializations of istreambuf_iterator shall have a trivial copy constructor,
1616
// a constexpr default constructor and a trivial destructor.
@@ -21,28 +21,31 @@
2121

2222
#include "test_macros.h"
2323

24-
int main(int, char**)
25-
{
26-
{
27-
typedef std::istreambuf_iterator<char> T;
28-
T it;
29-
assert(it == T());
24+
int main(int, char**) {
25+
{
26+
typedef std::istreambuf_iterator<char> T;
27+
T it;
28+
assert(it == T());
3029
#if TEST_STD_VER >= 11
31-
constexpr T it2;
32-
(void)it2;
30+
constexpr T it2;
31+
(void)it2;
3332
#endif
34-
}
33+
34+
ASSERT_NOEXCEPT(T());
35+
}
3536

3637
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
37-
{
38-
typedef std::istreambuf_iterator<wchar_t> T;
39-
T it;
40-
assert(it == T());
38+
{
39+
typedef std::istreambuf_iterator<wchar_t> T;
40+
T it;
41+
assert(it == T());
4142
#if TEST_STD_VER >= 11
42-
constexpr T it2;
43-
(void)it2;
43+
constexpr T it2;
44+
(void)it2;
4445
#endif
45-
}
46+
47+
ASSERT_NOEXCEPT(T());
48+
}
4649
#endif // TEST_HAS_NO_WIDE_CHARACTERS
4750

4851
return 0;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17
10+
11+
// <iterator>
12+
13+
// constexpr istreambuf_iterator(default_sentinel_t) noexcept; // since C++20
14+
15+
#include <iterator>
16+
#include <sstream>
17+
#include <cassert>
18+
19+
#include "test_macros.h"
20+
21+
int main(int, char**) {
22+
using T = std::istreambuf_iterator<char>;
23+
24+
{
25+
T it(std::default_sentinel);
26+
assert(it == T());
27+
}
28+
29+
{
30+
T it = std::default_sentinel;
31+
assert(it == T());
32+
}
33+
34+
{
35+
constexpr T it(std::default_sentinel);
36+
(void)it;
37+
}
38+
39+
ASSERT_NOEXCEPT(T(std::default_sentinel));
40+
41+
return 0;
42+
}

0 commit comments

Comments
 (0)