view::c_str 与 view::split 有问题吗?

Does view::c_str have issues with view::split?

给定

auto cstr = "quick brown fox";

我们有一组适配器只是为了拆分单词然后尝试将它们显示为格式化范围。

auto adaptors = ranges::view::split(' ') | ranges::view::all;

如果来源是string_view,没关系。

auto sv = std::string_view{cstr};
ranges::copy(sv | adaptors, ranges::ostream_iterator(std::cout,";") );

输出:[wandbox]

[q,u,i,c,k];[b,r,o,w,n];[f,o,x];

然后尝试使用 view::c_str

auto cstr_rng = ranges::view::c_str(cstr);
// Won't compile
// ranges::copy(cstr_rng | adaptors, ranges::ostream_iterator(std::cout,";") );

错误:[CE]

/opt/compiler-explorer/libs/rangesv3/trunk/include/range/v3/view/split.hpp: In instantiation of 'ranges::v3::split_view<Rng, Fun>::cursor<IsConst>::cursor(ranges::v3::split_view<Rng, Fun>::cursor<IsConst>::fun_ref_t, ranges::v3::iterator_t<Rng>, ranges::v3::sentinel_t<Rng>) [with bool IsConst = true; Rng = ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>; Fun = ranges::v3::view::split_fn::element_pred<ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>&>; ranges::v3::split_view<Rng, Fun>::cursor<IsConst>::fun_ref_t = ranges::v3::view::split_fn::element_pred<ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>&>; ranges::v3::iterator_t<Rng> = ranges::v3::_basic_iterator_::basic_iterator<ranges::v3::adaptor_cursor<const char*, ranges::v3::adaptor_base> >; ranges::v3::sentinel_t<Rng> = ranges::v3::adaptor_sentinel<ranges::v3::unreachable, ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>::sentinel_adaptor>]':
/opt/compiler-explorer/libs/rangesv3/trunk/include/range/v3/view/split.hpp:128:69:   required from 'ranges::v3::split_view<Rng, Fun>::cursor<true> ranges::v3::split_view<Rng, Fun>::begin_cursor() const [with int _concept_requires_125 = 42; typename std::enable_if<((_concept_requires_125 == 43) || (ranges::v3::concepts::models<ranges::v3::concepts::Invocable, const Fun&, decltype (ranges::v3::function_objects::begin(declval<T&>())), decltype (ranges::v3::function_objects::end(declval<Rng&>()))>() && ranges::v3::concepts::models<ranges::v3::concepts::Range, const D>())), int>::type <anonymous> = 0; Rng = ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>; Fun = ranges::v3::view::split_fn::element_pred<ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>&>]'
/opt/compiler-explorer/libs/rangesv3/trunk/include/range/v3/range_access.hpp:176:13:   required from 'static constexpr decltype (static_cast<const Rng&>(rng).begin_cursor()) ranges::v3::range_access::begin_cursor(Rng&, int) [with Rng = const ranges::v3::split_view<ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>, ranges::v3::view::split_fn::element_pred<ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>&> >; decltype (static_cast<const Rng&>(rng).begin_cursor()) = ranges::v3::split_view<ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>, ranges::v3::view::split_fn::element_pred<ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>&> >::cursor<true>]'
/opt/compiler-explorer/libs/rangesv3/trunk/include/range/v3/view_facade.hpp:93:51:   required from 'ranges::v3::detail::facade_iterator_t<const D> ranges::v3::view_facade<Derived, C>::begin() const [with D = ranges::v3::split_view<ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>, ranges::v3::view::split_fn::element_pred<ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>&> >; int _concept_requires_90 = 42; typename std::enable_if<((_concept_requires_113 == 43) || typename ranges::v3::concepts::Same::same<C, Cur>::type()), int>::type <anonymous> = 0; Derived = ranges::v3::split_view<ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>, ranges::v3::view::split_fn::element_pred<ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>&> >; ranges::v3::cardinality Cardinality = (ranges::v3::cardinality)-1; ranges::v3::detail::facade_iterator_t<const D> = ranges::v3::_basic_iterator_::basic_iterator<ranges::v3::split_view<ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>, ranges::v3::view::split_fn::element_pred<ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>&> >::cursor<true> >; typename std::decay<decltype (ranges::v3::range_access::begin_cursor(declval<const D&>(), 42))>::type = ranges::v3::split_view<ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>, ranges::v3::view::split_fn::element_pred<ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>&> >::cursor<true>]'
/opt/compiler-explorer/libs/rangesv3/trunk/include/range/v3/begin_end.hpp:58:17:   required from 'static constexpr I ranges::v3::_begin_::fn::impl_(R&, int) [with R = const ranges::v3::split_view<ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>, ranges::v3::view::split_fn::element_pred<ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>&> >; I = ranges::v3::_basic_iterator_::basic_iterator<ranges::v3::split_view<ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>, ranges::v3::view::split_fn::element_pred<ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>&> >::cursor<true> >; int _concept_requires_56 = 42; typename std::enable_if<((_concept_requires_56 == 43) || ranges::v3::concepts::models<ranges::v3::concepts::Iterator, I>()), int>::type <anonymous> = 0]'
/opt/compiler-explorer/libs/rangesv3/trunk/include/range/v3/begin_end.hpp:76:17:   required from 'constexpr decltype (ranges::v3::_begin_::fn::impl_(r, 42)) ranges::v3::_begin_::fn::operator()(R&) const [with R = const ranges::v3::split_view<ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>, ranges::v3::view::split_fn::element_pred<ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>&> >; decltype (ranges::v3::_begin_::fn::impl_(r, 42)) = ranges::v3::_basic_iterator_::basic_iterator<ranges::v3::split_view<ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>, ranges::v3::view::split_fn::element_pred<ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>&> >::cursor<true> >]'
/opt/compiler-explorer/libs/rangesv3/trunk/include/range/v3/begin_end.hpp:145:56:   [ skipping 6 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/opt/compiler-explorer/libs/rangesv3/trunk/include/range/v3/utility/functional.hpp:718:13:   required by substitution of 'template<class Arg, class Pipe> static decltype (pipe(static_cast<Arg&&>(arg))) ranges::v3::pipeable<ranges::v3::view::all_fn>::pipe<Arg, Pipe>(Arg&&, Pipe) [with Arg = ranges::v3::split_view<ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>, ranges::v3::view::split_fn::element_pred<ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>&> >; Pipe = ranges::v3::view::all_fn]'
/opt/compiler-explorer/libs/rangesv3/trunk/include/range/v3/utility/functional.hpp:728:9:   required by substitution of 'template<class Arg, class Pipe, int _concept_requires_726, typename std::enable_if<((_concept_requires_726 == 43) || ((! ranges::v3::is_pipeable<T>()) && ranges::v3::is_pipeable<Pipe>())), int>::type <anonymous> > decltype (ranges::v3::pipeable_access::impl<Pipe>::pipe(static_cast<Arg&&>(arg), pipe)) ranges::v3::operator|(Arg&&, Pipe) [with Arg = ranges::v3::split_view<ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>, ranges::v3::view::split_fn::element_pred<ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>&> >; Pipe = ranges::v3::view::all_fn; int _concept_requires_726 = 42; typename std::enable_if<((_concept_requires_726 == 43) || ((! ranges::v3::is_pipeable<T>()) && ranges::v3::is_pipeable<Pipe>())), int>::type <anonymous> = 0]'
/opt/compiler-explorer/libs/rangesv3/trunk/include/range/v3/utility/functional.hpp:644:17:   required by substitution of 'template<class Arg> decltype (((static_cast<Arg&&>(arg) | ((const ranges::v3::detail::composed_pipe<ranges::v3::view::view<ranges::v3::detail::pipeable_binder<std::_Bind<ranges::v3::view::split_fn(std::_Placeholder<1>, char)> > >, ranges::v3::view::all_fn>*)this)->ranges::v3::detail::composed_pipe<ranges::v3::view::view<ranges::v3::detail::pipeable_binder<std::_Bind<ranges::v3::view::split_fn(std::_Placeholder<1>, char)> > >, ranges::v3::view::all_fn>::pipe0_) | ((const ranges::v3::detail::composed_pipe<ranges::v3::view::view<ranges::v3::detail::pipeable_binder<std::_Bind<ranges::v3::view::split_fn(std::_Placeholder<1>, char)> > >, ranges::v3::view::all_fn>*)this)->ranges::v3::detail::composed_pipe<ranges::v3::view::view<ranges::v3::detail::pipeable_binder<std::_Bind<ranges::v3::view::split_fn(std::_Placeholder<1>, char)> > >, ranges::v3::view::all_fn>::pipe1_)) ranges::v3::detail::composed_pipe<ranges::v3::view::view<ranges::v3::detail::pipeable_binder<std::_Bind<ranges::v3::view::split_fn(std::_Placeholder<1>, char)> > >, ranges::v3::view::all_fn>::operator()<Arg>(Arg&&) const [with Arg = ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>&]'
/opt/compiler-explorer/libs/rangesv3/trunk/include/range/v3/utility/functional.hpp:718:13:   required by substitution of 'template<class Arg, class Pipe> static decltype (pipe(static_cast<Arg&&>(arg))) ranges::v3::pipeable<ranges::v3::detail::pipeable_binder<ranges::v3::detail::composed_pipe<ranges::v3::view::view<ranges::v3::detail::pipeable_binder<std::_Bind<ranges::v3::view::split_fn(std::_Placeholder<1>, char)> > >, ranges::v3::view::all_fn> > >::pipe<Arg, Pipe>(Arg&&, Pipe) [with Arg = ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>&; Pipe = ranges::v3::detail::pipeable_binder<ranges::v3::detail::composed_pipe<ranges::v3::view::view<ranges::v3::detail::pipeable_binder<std::_Bind<ranges::v3::view::split_fn(std::_Placeholder<1>, char)> > >, ranges::v3::view::all_fn> >]'
/opt/compiler-explorer/libs/rangesv3/trunk/include/range/v3/utility/functional.hpp:728:9:   required by substitution of 'template<class Arg, class Pipe, int _concept_requires_726, typename std::enable_if<((_concept_requires_726 == 43) || ((! ranges::v3::is_pipeable<T>()) && ranges::v3::is_pipeable<Pipe>())), int>::type <anonymous> > decltype (ranges::v3::pipeable_access::impl<Pipe>::pipe(static_cast<Arg&&>(arg), pipe)) ranges::v3::operator|(Arg&&, Pipe) [with Arg = ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>&; Pipe = ranges::v3::detail::pipeable_binder<ranges::v3::detail::composed_pipe<ranges::v3::view::view<ranges::v3::detail::pipeable_binder<std::_Bind<ranges::v3::view::split_fn(std::_Placeholder<1>, char)> > >, ranges::v3::view::all_fn> >; int _concept_requires_726 = 42; typename std::enable_if<((_concept_requires_726 == 43) || ((! ranges::v3::is_pipeable<T>()) && ranges::v3::is_pipeable<Pipe>())), int>::type <anonymous> = 0]'
<source>:20:29:   required from here
/opt/compiler-explorer/libs/rangesv3/trunk/include/range/v3/view/split.hpp:114:36: error: no match for call to '(const ranges::v3::invoke_fn) (ranges::v3::split_view<ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>, ranges::v3::view::split_fn::element_pred<ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char>&> >::cursor<true>::fun_ref_t&, ranges::v3::iterator_t<ranges::v3::delimit_view<ranges::v3::iterator_range<const char*, ranges::v3::unreachable>, char> >&, ranges::v3::_basic_iterator_::basic_iterator<ranges::v3::adaptor_cursor<const char*, ranges::v3::adaptor_base> >)'
                     auto p = invoke(fun, first, ranges::next(first));
                          ~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

这是 view::c_str 的某种限制还是 view::c_str 和 view::split 之间存在一些问题?

godbolt.org/g/bTK4Yp

wandbox.org/permlink/ZkDmSkBxPg80oebS

此错误是由于 split_view 中的错误造成的。具体来说,在 split_view::cursor::cursor():

cursor(fun_ref_t fun, iterator_t<Rng> first, sentinel_t<Rng> last)
    : cur_(first), last_(last), fun_(fun)
{
    // For skipping an initial zero-length match
    auto p = invoke(fun, first, ranges::next(first)); // <----
    zero_ = p.first && first == p.second;
}

尽管 the predicate function implementations on lines 150-199 接受来自底层范围的迭代器和 sentinel,但标记的行使用来自底层范围的两个迭代器调用 fun

20180228更新:

修复已签入,此错误不应再在 range-v3 master 上重现。