c++stliteratorinput-iterator

Why does std::find_if used on std::istream_iterators seem to return the last element?


I am learning C++ through Accelerated C++ by Andrew Koenig and Barbara E. Moo. I am trying to understand how input operators work and their relation to STL algorithms.

Here is the piece of code that confuses me:

#include <iostream>
#include <iterator>
#include <algorithm>
#include <cctype>

bool space(char c)
{
    return std::isspace(c);
}

int main()
{
    std::istream_iterator<char> i = std::find_if(
        std::istream_iterator<char>(std::cin),
        std::istream_iterator<char>(),
        space);
    std::cout << *i << std::endl;
    return 0;
}

The code compiles fine but when I run it on any input what it outputs is the last character entered. For example, I expected the output of 123 456 to be but it actually is 6. Similarly, I expected the output of 123456 to be some error because we try to access an element that doesn't exist, yet the output is again . What am I missing?


Solution

  • Why doesn't 123 456 as input produce as output?

    From cppreference:

    When reading characters, std::istream_iterator skips whitespace by default (unless disabled with std::noskipws or equivalent), while std::istreambuf_iterator does not.

    Switching to std::istreambuf_iterator gives the desired behaviour: https://wandbox.org/permlink/RRt8kvyqyvbO1p8m


    Why doesn't 123456 as input produce an error?

    If there is no space in the input, find_if will return its 2nd argument, which is the end-of-stream iterator.

    Dereferencing the end-of-stream iterator is undefined behaviour, which is not guaranteed to produce an error. In fact it doesn't guarantee anything, which means your program might just print the last character in your input.