Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

istreambuf_iterator constructed with istream at eof isn't detected #149

Closed
cjdb opened this issue May 18, 2018 · 2 comments
Closed

istreambuf_iterator constructed with istream at eof isn't detected #149

cjdb opened this issue May 18, 2018 · 2 comments

Comments

@cjdb
Copy link
Collaborator

cjdb commented May 18, 2018

When comparing a freshly-constructed istreambuf_iterator with an istream that has already reached EOF, istreambuf_iterator != default_sentinel returns true. This behaviour differs from std::istreambuf_iterator.

#include <experimental/ranges/iterator>
#include <iostream>
#include <sstream>

int main()
{
   auto in = std::istringstream{"hello"};
   for (auto i = __stl2::istreambuf_iterator<char>{in}; i != __stl2::default_sentinel{}; ++i) {
      std::cout << *i << '\n';
   }
   for (auto i = __stl2::istreambuf_iterator<char>{in}; i != __stl2::default_sentinel{}; ++i) {
      std::cout << *i << '\n'; // Line 12
   }
}

Interestingly, this is only on the first pass: commenting out line 12 causes the program to complete without error.

@cjdb cjdb changed the title istreambuf constructed with istream at eof isn't detected istreambuf_iterator constructed with istream at eof isn't detected May 18, 2018
@cjdb
Copy link
Collaborator Author

cjdb commented May 18, 2018

This might be related to #28.

@CaseyCarter
Copy link
Owner

CaseyCarter commented May 18, 2018

istreambuf_iterator is, unsuprisingly, broken. [istreambuf.iterator.cons]:

1 For each istreambuf_­iterator constructor in this subclause, an end-of-stream iterator is constructed if and only if the exposition-only member sbuf_­ is initialized with a null pointer value.

constexpr istreambuf_iterator() noexcept;

2 Effects: Initializes sbuf_­ with nullptr.

istreambuf_iterator(istream_type& s) noexcept;

3 Effects: Initializes sbuf_­ with s.rdbuf().

istreambuf_iterator(streambuf_type* s) noexcept;

4 Effects: Initializes sbuf_­ with s.

istreambuf_iterator(const proxy& p) noexcept;

5 Effects: Initializes sbuf_­ with p.sbuf_­.

[istreambuf.iterator.ops] para 5 & 6:

bool equal(const istreambuf_iterator& b) const;

5 Returns: true if and only if both iterators are at end-of-stream, or neither is at end-of-stream, regardless of what streambuf object they use.

template<class charT, class traits>
  bool operator==(const istreambuf_iterator<charT,traits>& a,
                  const istreambuf_iterator<charT,traits>& b);

6 Returns: a.equal(b)

Yet this program:

#include <cassert>
#include <iterator>
#include <sstream>

int main()
{
   auto in = std::istringstream{};
   assert(in.rdbuf() != nullptr);
   using I = std::istreambuf_iterator<char>;
   // Since in.rdbuf() != nullptr, I{in} does not construct an end-of-stream iterator. Right?
   assert(I{in} != I{}); 
}

Fails on on libstdc++/libc++/STLSTL.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants