Opened 7 years ago

Closed 7 years ago

#11274 closed Bugs (invalid)

coroutine's iterators don't fully comply

Reported by: Akim Demaille <akim.demaille@…> Owned by: olli
Milestone: To Be Determined Component: coroutine
Version: Boost 1.58.0 Severity: Problem
Keywords: Cc:

Description

Hi!

The following example fails to compile cleanly. I use a boost range adaptor to slice an "endless" coroutine, used as a generator: source | strided(10).

// begin:header
#include <iostream>
#include <boost/coroutine/coroutine.hpp>
#include <boost/range/adaptor/strided.hpp>

using namespace boost::adaptors;
using coro_t = boost::coroutines::asymmetric_coroutine<int>;
// end:header

// begin:func
void fibo(coro_t::push_type& sink)
{
  int first = 1, second = 1;
  sink(first);
  sink(second);
  for (;;)
    {
      int third = first + second;
      first = second;
      second = third;
      sink(third);
    }
};
// end:func

// begin:main
int main()
{
  auto source = coro_t::pull_type{fibo};
  for (auto i : source | strided(10))
    std::cout << i <<  " ";
  std::cout << '\n';
}
// end:main

// CXXFLAGS: -lboost_coroutine-mt -lboost_system-mt

It results in:

clang++ -stdlib=libc++ -isystem/opt/local/include -std=c++11 -Wall -Wextra -ggdb -L/opt/local/lib  -lboost_coroutine-mt -lboost_system-mt -o 6-concurrency/coroutine.exe 6-concurrency/coroutine.cc && 6-concurrency/coroutine.exe </dev/null >6-concurrency/coroutine.log.tmp 2>&1 && mv 6-concurrency/coroutine.log.tmp 6-concurrency/coroutine.log && { test "1" != 1 || cat 6-concurrency/coroutine.log; }
In file included from 6-concurrency/coroutine.cc:3:
In file included from /opt/local/include/boost/coroutine/coroutine.hpp:10:
In file included from /opt/local/include/boost/coroutine/asymmetric_coroutine.hpp:17:
In file included from /opt/local/include/boost/range.hpp:18:
In file included from /opt/local/include/boost/range/functions.hpp:20:
In file included from /opt/local/include/boost/range/size.hpp:21:
In file included from /opt/local/include/boost/range/size_type.hpp:20:
In file included from /opt/local/include/boost/range/concepts.hpp:20:
In file included from /opt/local/include/boost/iterator/iterator_concepts.hpp:10:
/opt/local/include/boost/iterator/iterator_categories.hpp:119:60: error: no type named
      'iterator_category' in
      'std::__1::iterator_traits<boost::coroutines::pull_coroutine<int>::const_iterator>'
        typename boost::detail::iterator_traits<Iterator>::iterator_category
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~
/opt/local/include/boost/range/adaptor/strided.hpp:606:26: note: in instantiation of
      template class
      'boost::iterators::iterator_traversal<boost::coroutines::pull_coroutine<int>::const_iterator>'
      requested here
                typename iterator_traversal<
                         ^
/opt/local/include/boost/range/adaptor/strided.hpp:660:16: note: in instantiation of
      default argument for 'strided_range<const boost::coroutines::pull_coroutine<int>
      >' required here
        inline strided_range<const Rng>
               ^~~~~~~~~~~~~~~~~~~~~~~~
6-concurrency/coroutine.cc:30:24: note: while substituting deduced template arguments
      into function template 'operator|' [with Rng =
      boost::coroutines::pull_coroutine<int>, Difference = int]
  for (auto i : source | strided(10))
                       ^
In file included from 6-concurrency/coroutine.cc:4:
/opt/local/include/boost/range/adaptor/strided.hpp:627:21: error: no matching function
      for call to 'make_begin_strided_iterator'
                    range_detail::make_begin_strided_iterator(
                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/local/include/boost/range/adaptor/strided.hpp:656:20: note: in instantiation of
      function template specialization
      'boost::range_detail::strided_range<boost::coroutines::pull_coroutine<int>,
      boost::iterators::single_pass_traversal_tag>::strided_range<int>' requested here
            return strided_range<Rng>(stride.val, rng);
                   ^
6-concurrency/coroutine.cc:30:24: note: in instantiation of function template
      specialization
      'boost::range_detail::operator|<boost::coroutines::pull_coroutine<int>, int>'
      requested here
  for (auto i : source | strided(10))
                       ^
/opt/local/include/boost/range/adaptor/strided.hpp:412:9: note: candidate function
      [with Rng = boost::coroutines::pull_coroutine<int>, Difference = int] not
      viable: no known conversion from 'typename iterator_traversal<typename
      range_iterator<pull_coroutine<int> >::type>::type' (aka
      'boost::iterators::single_pass_traversal_tag') to
      'boost::iterators::forward_traversal_tag' for 3rd argument
        make_begin_strided_iterator(
        ^
/opt/local/include/boost/range/adaptor/strided.hpp:476:9: note: candidate function
      [with Rng = boost::coroutines::pull_coroutine<int>, Difference = int] not
      viable: no known conversion from 'typename iterator_traversal<typename
      range_iterator<pull_coroutine<int> >::type>::type' (aka
      'boost::iterators::single_pass_traversal_tag') to
      'boost::iterators::bidirectional_traversal_tag' for 3rd argument
        make_begin_strided_iterator(
        ^
/opt/local/include/boost/range/adaptor/strided.hpp:544:9: note: candidate function
      [with Rng = boost::coroutines::pull_coroutine<int>, Difference = int] not
      viable: no known conversion from 'typename iterator_traversal<typename
      range_iterator<pull_coroutine<int> >::type>::type' (aka
      'boost::iterators::single_pass_traversal_tag') to
      'boost::iterators::random_access_traversal_tag' for 3rd argument
        make_begin_strided_iterator(
        ^
/opt/local/include/boost/range/adaptor/strided.hpp:428:9: note: candidate function
      [with Rng = boost::coroutines::pull_coroutine<int>, Difference = int] not
      viable: no known conversion from 'typename iterator_traversal<typename
      range_iterator<pull_coroutine<int> >::type>::type' (aka
      'boost::iterators::single_pass_traversal_tag') to
      'boost::iterators::forward_traversal_tag' for 3rd argument
        make_begin_strided_iterator(
        ^
/opt/local/include/boost/range/adaptor/strided.hpp:494:9: note: candidate function
      [with Rng = boost::coroutines::pull_coroutine<int>, Difference = int] not
      viable: no known conversion from 'typename iterator_traversal<typename
      range_iterator<pull_coroutine<int> >::type>::type' (aka
      'boost::iterators::single_pass_traversal_tag') to
      'boost::iterators::bidirectional_traversal_tag' for 3rd argument
        make_begin_strided_iterator(
        ^
/opt/local/include/boost/range/adaptor/strided.hpp:560:9: note: candidate function
      [with Rng = boost::coroutines::pull_coroutine<int>, Difference = int] not
      viable: no known conversion from 'typename iterator_traversal<typename
      range_iterator<pull_coroutine<int> >::type>::type' (aka
      'boost::iterators::single_pass_traversal_tag') to
      'boost::iterators::random_access_traversal_tag' for 3rd argument
        make_begin_strided_iterator(
        ^
2 errors generated.
make[1]: *** [6-concurrency/coroutine.log] Error 1
make[1]: Leaving directory `/Users/akim/src/lrde/cours/cxxa'
make: *** [all] Error 2

Compilation exited abnormally with code 2 at Thu May  7 10:29:24

It seems to me that the problem is that const_iterator does not define iterator_category, and it should. Maybe Boost.Coroutine should use Boost.IteratorFacade to define its iterators?

Change History (1)

comment:1 by olli, 7 years ago

Resolution: invalid
Status: newclosed

It's a problem of boost.range (1.58): 'Although the doc says strided supports SinglePassRange, the current implementation of <boost/range/adaptor/strided.hpp> does not support SinglePassRange; it needs ForwardRange.'

Note: See TracTickets for help on using tickets.