
2017-07-04 0:49 GMT+02:00 Ion Gaztañaga via Boost <boost@lists.boost.org>:
On 03/07/2017 8:41, Andrzej Krzemienski via Boost wrote:
Those Boost iterators provide two distinct tags:
1. STL-conformant *iterator tag* (in the case of zip-iterator it is
I don't think so. The following example:
#include <iostream> #include <boost/iterator/zip_iterator.hpp> #include <boost/tuple/tuple.hpp>
template<class Iterator> void print_type(Iterator) { std::cout << typeid(typename Iterator::iterator_category).name() << std::endl; }
int main() { const int N=1; int keys[N]; double values[N]; print_type(boost::make_zip_iterator(boost::make_tuple(&keys[0], &values[0]))); return 0; }
prints in MSVC 2017
"struct boost::iterators::detail::iterator_category_with_traversal<struct std::input_iterator_tag,struct boost::iterators::random_acces s_traversal_tag>"
instead of "std::input_iterator_tag". That type inherits from "std::input_iterator_tag" but it's not an standard tag type, so IMHO, it's a non-conforming iterator.
Not necessarily non-conforming. I guess one could come up with such interpretation, but the Standatd is not really explicit about this. The most relevant sentence, "`iterator_category` shall be defined to be the most specific category tag that describes the iterator’s behavior" -- it could be read as "do not use any tag but these five" or "if you define a tag for RandomAccessIterator don't defien iterator_category as forward_iterator_tag". The example illustrating the intended usage of tags in [std.iterator.tags] also shows that it works fine with tags inherited from the standard ones. This additionally seems to be backed up by MSVC implementation of std::prev: ``` // TEMPLATE FUNCTION prev template<class _BidIt> inline _BidIt prev(_BidIt _First, typename iterator_traits<_BidIt>::difference_type _Off = 1) { // decrement iterator * static_assert(is_base_of<bidirectional_iterator_tag, typename iterator_traits<_BidIt>::iterator_category>::value, "prev requires bidirectional iterator");* _STD advance(_First, -_Off); return (_First); } ``` And by Ranges TS: ``` template <class I> concept bool BidirectionalIterator() { return ForwardIterator<I>() && * DerivedFrom<iterator_category_**t<I>, bidirectional_iterator_tag>()* && requires(I i) { { --i } -> Same<I&>; { i-- } -> Same<I>; }; } ``` Also, the GCC problem is not caused by iterator tags deriving from the standard tags, but because std::prev is instantiated with an InputIterator. Regards, &rzej;