Boost logo

Boost :

Subject: Re: [boost] [range]slicing any_range
From: Takatoshi Kondo (redboltz_at_[hidden])
Date: 2013-12-24 06:48:35


I analyzed my program on the following environment:

g++ 4.8.2
Linux archboltz 3.12.4-1-ARCH #1 SMP PREEMPT Sun Dec 8 21:18:00 CET
2013 x86_64 GNU/Linux

In the file iterator_range_core.hpp , std::advance() is called. The
type of BOOST_DEDUCED_TYPENAME range_iterator<Range>::type is
boost::iterator_facade<
  boost::range_detail::any_iterator<
    int, boost::random_access_traversal_tag, int, long,
boost::any_iterator_buffer<64ul>
>,
  int,
  boost::random_access_traversal_tag,
  int,
  long
>

            template< class Range >
            inline iterator_range< BOOST_DEDUCED_TYPENAME
range_iterator<Range>::type >
            make_range_impl( Range& r,
                             BOOST_DEDUCED_TYPENAME
range_difference<Range>::type advance_begin,
                             BOOST_DEDUCED_TYPENAME
range_difference<Range>::type advance_end )
            {
                //
                // Not worth the effort
                //
                //if( advance_begin == 0 && advance_end == 0 )
                // return make_iterator_range( r );
                //

                BOOST_DEDUCED_TYPENAME range_iterator<Range>::type
                    new_begin = boost::begin( r ),
                    new_end = boost::end( r );
                std::advance( new_begin, advance_begin );
                std::advance( new_end, advance_end );
                return make_iterator_range( new_begin, new_end );
            }

When std::advance() is called, it dispatched to the InputIterator
overloading version of __advance(). My expectation was that dispatched
to the RandomAccessIterator overloading version of __advance().

stl_iterator_base_funcs.h:121

  template<typename _InputIterator, typename _Distance>
    inline void
    __advance(_InputIterator& __i, _Distance __n, input_iterator_tag)
    {
      // concept requirements
      __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
      _GLIBCXX_DEBUG_ASSERT(__n >= 0);
      while (__n--)
++__i;
    }

Is that the problem relate to https://svn.boost.org/trac/boost/ticket/1296 ?

To check the behavior of boost::random_access_traversal_tag and
std::advance, I wrote the following code:

#include <boost/iterator/iterator_facade.hpp>
#include <vector>
#include <iostream>

struct my_iter:boost::iterator_facade<my_iter, int,
boost::random_access_traversal_tag> {
  void advance(std::size_t v) {
    std::cout << "advance() is called with arg " << v << std::endl;
  }
};

int main() {
  my_iter mit;
  std::advance(mit, 1);
}

Output:
advance() is called with arg 1

When std::advance() is called, it dispatched to the
RandomAccessIterator overloading version of __advance().

stl_iterator_base_funcs.h:148

 template<typename _RandomAccessIterator, typename _Distance>
    inline void
    __advance(_RandomAccessIterator& __i, _Distance __n,
              random_access_iterator_tag)
    {
      // concept requirements
      __glibcxx_function_requires(_RandomAccessIteratorConcept<
 _RandomAccessIterator>)
      __i += __n;
    }

And then, operator += called my_iter::advance().

I got stuck. Why any_range with boost::random_access_traversal_tag and
my_iter with boost::random_access_traversal_tag behave differently.
They both iterator_facade.

Takatoshi Kondo

On Tue, Dec 24, 2013 at 6:55 AM, Takatoshi Kondo <redboltz_at_[hidden]> wrote:
> Hello,
>
> I'm using the Boost.Range library (Version:1.55.0). When I use
> any_range with sliced adaptor, slicing operation doesn't return. Is my
> code something wrong? If it is a bug, I will create a ticket.
>
> Here is the minimized code that reproduces the situation:
>
> #include <vector>
> #include <iostream>
> #include <cassert>
> #include <boost/range/any_range.hpp>
> #include <boost/range/adaptor/sliced.hpp>
>
> typedef boost::any_range<int, boost::random_access_traversal_tag, int,
> std::ptrdiff_t> int_range;
>
> int main() {
> std::vector<int> v;
> v.push_back(0);
> v.push_back(1);
> v.push_back(2);
> { // works fine
> std::cout << "slice vector" << std::endl;
> int_range ir1 = v | boost::adaptors::sliced(0,2);
> std::cout << "slice vector finished" << std::endl;
> assert(ir1[0] == 0);
> assert(ir1[1] == 1);
> assert(ir1.size() == 2);
> }
> {
> int_range ir2(v);
> std::cout << "slice any_range" << std::endl;
> int_range ir3 = ir2 | boost::adaptors::sliced(0,2); // never return...
> std::cout << "slice any_range finished" << std::endl;
> assert(ir3[0] == 0);
> assert(ir3[1] == 1);
> assert(ir3.size() == 2);
> }
> }
>
> Takatoshi Kondo


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk