Dne 05.05.2014 13:40, Neil Groves napsal:
On Mon, May 5, 2014 at 11:03 AM, Jan Hudec
wrote: Hello All,
The documentation of [Single Pass Range][1] in Boost.Range says that there should be both `iterator` and `const_iterator` associated types and both const and non-const overloads for `begin` and `end`. However if it is really a single-pass range, I don't see a way to implement a `const_iterator` that would work on `const` reference to the range, because the `operator++` of the iterator involves calling a non-const method of the range.
I think that your statements indicate that you have a misunderstanding about implementing iterators. The word "const" does not refer to the iterator type itself but to the reference type. It is not possible without resort to very perverse use of the "mutable" keyword to implement a const_iterator to refer to any type. Of course, const_iterator is part of every standard container so this is not an idiom that is specific to Boost.Range.
All containers are at least forward ranges, not merely single pass ones. Since iterating a forward range does not change it, there is no problem for it to have a `const` `begin()` and `end()` methods (returning const iterators). What I had issue with is single pass range. Consider something that behaves like `std::istream`. The `std::istream_iterator` can be only constructed from non-const reference to `std::istream`, because the `std::istream_iterator::operator++` (and the constructor itself) call the `std::istream::operator>>`, which is non-const. Of course for `std::istream` a wrapper is needed anyway, because the stream can return various types, so the wrapper has to specify which one is desired. But if I have a class that behaves similarly, but returns a specific type, I still can't make it a range, because I still can't give it a `begin` that would accept const reference (I _can_ usually give it `end`, because for this kind of objects the end iterator is dummy, but that won't help).
For example the `std::istream_iterator::operator++` calls `std::istream::operator>>`, which is non-const and so there is no `const_istream_iterator`. The `istream_range` cheats around this a little, because the range is a wrapper around the stream, not the stream itself. But when I have similarly behaving class that I can make itself be a range, do I really have to work around this using a wrapper, or can the requirement be relaxed in practice?
I believe that you don't have a problem! A const_iterator can be implemented with non-const member functions. There are examples within the Boost.Range unit test code that show the use of extending Boost.Range for user defined types. These show the various methods for implementing this. There is also documentation that has an example extending via the const and mutable meta-functions here:
http://www.boost.org/doc/libs/1_55_0/libs/range/doc/html/range/reference/ext...
Well, it can't be implemented using non-const methods of the _range_
_itself_.
If I have a stream-like object
class int_reader {
...
int get_next(); // NOT const
};
than I can create iterators for it. But the iterators will look like
class int_reader_iterator :
boost::iterator_facade