Boost logo

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