views:

53

answers:

1

I'm using Boost.Range to pass around some data and a container class for this data. The data is loaded in a different thread and may in some cases not be ready yet. In this case the container is initialized with the default iterator_range, hence containing singular iterators. I'm doing assignments and copying of the data containers (hence the iterator_ranges). However, the iterator_range copy constructor calls begin() and end() which will assert when the original is singular. Therefor, it is not possible to copy an empty data container.

Is there any way to avoid this limitation?

Why is this limitation been implemented? The following works just fine, shouldn't ranges behave similarly?

typedef std::vector<int>::iterator iterator;
iterator it; // Singular
iterator it2 = it; // Works

boost::iterator_range<iterator> range; // Singular
boost::iterator_range<iterator> range2 = range; // Asserts in debug, but why?
+3  A: 

If by "works", you mean "it does not blow up with my current compiler version and invocation options", then yes, assigning a singular iterator might "work". Actually, the code

typedef std::vector<int>::iterator iterator;
iterator it; // Singular
iterator it2 = it; // Works

results in undefined behaviour, so you are up to the whims of your compiler for what may happen.

The C++ standard has this to say about it (section [lib.iterator.requirements]/5):

[...] Results of most expressions are undefined for singular values; the only exception is an assignment of a non-singular value to an iterator that holds a singular value. In this case the singular value is overwritten the same way as any other value. Dereferenceable and past-the-end values are always non-singular.

So, in the end ranges do work similar to single iterators. It just doesn't work the way you would like.
I think the best way is to use an empty range (explicitly constructed with to non-singular iterators) when the data is not yet ready, instead of a singular range.

Bart van Ingen Schenau
Interesting, I didn't know that this was a restriction - and haven't seen the effect before. Do you know the reasons for this behavior? It seems to work just fine with GCC and MSVC as we do this all the time in our application... :/
larsm
The reason for the undefined behaviour is that it is not even required to work for plain pointers. An implementation might trap when you look at a singular pointer value. The GCC and MSVC compilers just don't take any advantage of that and generate code that allows reading f invalid pointer values.
Bart van Ingen Schenau
It is also easy to think that the second iterator is initialized, when reading the code.
UncleBens