|
Boost : |
Subject: Re: [boost] [iterator][range] BoostIteratorTraversalConcepts-aware boost::advance/distance
From: Andrzej Krzemienski (akrzemi1_at_[hidden])
Date: 2017-07-04 08:26:07
2017-07-04 0:49 GMT+02:00 Ion Gaztañaga via Boost <boost_at_[hidden]>:
> 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;
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk