
Pointers, for example, are NULL on default-initialization (which is used in the default constructor of the iterator_range class).
And the above behaviour is tremendously useful, as in my previous example, for e.g. reading structured files, where certain components may or may not be present. To expand on my previous example, one of my libraries looks for data items in a binary file. The file may or may not have certain attributes. If present, these attributes are returned in an attribute range along with a range representing the data. The attribute range is in fact a range of iterators returning other ranges, while the data range is most of the time just some raw const pointers. These ranges are then passed to classes that will construct themselves appropriately depending on whether or not attributes are present.
I can well have my own iterators that are default-constructible and allow comparison in this state. And I don't understand why an iterator range of these iterators suddenly restricts me from being able to compare these iterators in empty(), for example.
Yes - just like I said - even std::istream_iterator<> is valid for comparison when default constructed.
I agree that is_singular is evil.
To be more precise, the new behaviour is evil. Previously it was fine, even though it wasn't very useful. Tom