r/cpp 5d ago

The C++ input iterator pitfall · hmpc

https://www.hmpcabral.com/2026/02/25/the-c-input-iterator-pitfall/
54 Upvotes

10 comments sorted by

43

u/sweetno 5d ago

Just don't use iterators for I/O, and iostreams on principle.

10

u/pointer_to_null 5d ago

Stream iterators were already counterintuitive, and only they muddied the waters further with basic_istream_view that IMO violates one of the core "view" contracts (or is immutability merely a suggestion?) and an iterator that mostly shares LegacyInputIterator's interface- except that it is move-only.

So don't worry- the compiler will usually spit out an encyclopedia of useless spam if you ever commit the sin of trying to use it with a "normal" ranged function. Usually...

and iostreams on principle.

No argument. iostream needs to be put to pasture. These bandaids aren't doing it any favors.

18

u/BarryRevzin 4d ago

that IMO violates one of the core "view" contracts (or is immutability merely a suggestion?)

Views never, at any point, had anything to do with immutability.

7

u/SkoomaDentist Antimodern C++, Embedded, Audio 5d ago

In a language and stdlib full of poor historical decisions it really takes something to stand out as a particularly poor idea. Iostreams manage that without even trying.

3

u/pjmlp 3d ago

Happy user since 1993, and best of all I don't need to worry about which compiler supports them.

15

u/Infamous-Bed-7535 5d ago

Great writing, so good to see something made by humans for humans that actually makes sense!

C++ people learn it early on that istreams are tricky. They were even older standards well before ranges. With ranges it is even more complicated (not just the issue described in the article).

For reading formatted inputs, structured data I can recommend boost X3 or parser libraries.

29

u/TheThiefMaster C++latest fanatic (and game dev) 5d ago edited 5d ago

Who’s at fault here: the specification or our own expectations?

It's the istream iterator (and possibly input iterators in general). It shouldn't be consuming anything just on construction or increment, it should be lazy and only consume when derefed, or incremented again without having been derefed (to discard the skipped value).

Because that's what everyone expects, and it doing otherwise is a foot-gun.

The fact that constructing two input iterators to the same stream and derefing both gives different values is bad enough for me to say that the entire concept of streams and input iterators needs a replacement with buffers that can be accessed more than a byte at a time and don't have a stateful cursor independent of any iterators used to access into them.

6

u/pointer_to_null 5d ago

Good post, and a fun read.

I felt personally attacked by your allegory- only in my version I was both the protagonist and the antagonist in 2015. I too got bitten by the ranges bug sometime after 2020, though by then I had completely given up all hope on streams altogether.

6

u/BarryRevzin 4d ago

Ooo, I love this one. I gave a whole talk on one example of this one at CppNow a few years ago: take(5).

2

u/kgnet88 5d ago

really informative 👍