boostorg / range

Boost.org range module
http://boost.org/libs/range
42 stars 101 forks source link

handle composite iterator traversals in iterator_range #13

Closed ericniebler closed 10 years ago

ericniebler commented 10 years ago

Commit [654ae838ee5228eec9006146cd1562c46d90f9d2] broke several Boost.Accumulators tests, and regressed functionality of boost::iterator_range for several kinds of iterators. The change assumes that boost::iterator_traversal returns one of a known set of traversal types. That's not true. It is merely required to return a type convertible to one of the known traversal types. Many iterators have such a traversal category. In particular, many of the iterators produced by Boost.Iterators have a composite iterator category/traversal (see boost::detail::iterator_category_with_traversal in boost/iterator/detail/facade_iterator_category.hpp).

This change makes accommodations for composite iterator categories. Tested with gcc-4.8 and msvc-12.0.

The following is a program that fails without this change:

#include <functional>
#include <boost/range/iterator_range.hpp>
#include <boost/iterator/counting_iterator.hpp>
#include <boost/iterator/transform_iterator.hpp>

typedef
    boost::transform_iterator<
        std::binder1st<std::multiplies<std::size_t> >
      , boost::counting_iterator<std::size_t>
    >
times2_iterator;

int main()
{
    times2_iterator i =
        boost::make_transform_iterator(
            boost::make_counting_iterator(0u),
            std::bind1st(std::multiplies<std::size_t>(), 2));
    boost::iterator_range<times2_iterator> u(i,i);
    auto x = u[4];
}