Subject: Re: [boost] [iterator][range] BoostIteratorTraversalConcepts-aware boost::advance/distance
From: Andrzej Krzemienski (akrzemi1_at_[hidden])
Date: 2017-07-03 06:41:44
2017-07-03 0:53 GMT+02:00 Ion GaztaÃ±aga via Boost <boost_at_[hidden]>:
> On 30/06/2017 9:03, Andrzej Krzemienski via Boost wrote:
> So according to STL rules zip-iterator can only be an InputIterator, even
>> though you have random-access capability. And in fact, zip-iterator has
>> iterator_category tag of `std::input_iterator_tag`, but apart from that it
>> provides a Boost "traversal category" tag, which just tell how you get to
>> the next object in the colleciton and not about its reference type.
> AFAIK Boost.Iterator can define iterator_category as something derived
> from a standard tag, but that "something" could not be any of standard
> tags, so I think it's non-conformant.
> A container could check through SFINAE if the tag of an iterator is
> exactly one of the standard provided ones. If Boost.Iterator defines
> iterator_category to anything that is not exactly a standard tag it won't
> be accepted by the container.
Those Boost iterators provide two distinct tags:
1. STL-conformant *iterator tag* (in the case of zip-iterator it is
2. Boost-specific *iterator traversal tag*.
So, Boost algorithms take advantage of the *iterator traversal tag*, but
the iterator is still recognized as an STL container through the *iterator
tag*, and still can be used with STL algorithms.
The source of the UB is that `std::prev` *requires* that the iterator
passed to it is at least a BidirectionalIterator, and zip-iterator is not
(it is a legal OutputIterator). And while it is easy to check this with a
type trait at compile-time (and Clang and MSVC do check this), technically
not meeting these constraints is an UB, and GCC, because it is not required
to check it, indeed does not check it.