我有一对迭代器,我想使用ranges::views::filter(some_predicate)它(与管道运算符一起)。AFAIU 我应该首先将我的迭代器对转换为视图。我尝试ranges::subrange(first, last)这样做,但我\xe2\x80\x99m 收到可怕的错误消息。
注1:I\xe2\x80\x99m使用C++14和range-v3版本0.9.1(与gcc-5.5兼容的最后一个版本)。如果使用 C++17/20 和/或使用 C++20 std::ranges 时解决方案不同,I\xe2\x80\x99m 也有兴趣知道发生了什么变化。
\n注2:我发现range-v3 的文档严重缺乏,所以我使用cppreference.com \xe2\x80\x99m 。如果你知道更好的文档,我\xe2\x80\x99m非常感兴趣。
\n编辑:
\n在我的真实代码中, I\xe2\x80\x99m 包装了一个 java 风格的遗留迭代器(它有一个next()方法而不是operator++/ operator*。I\xe2\x80\x99m 将它们包装在 C++ 兼容的包装器中。然后我尝试将其转换为包装到视图中,最后过滤它。我在godbolt上重现了一个最小的示例。iterator_range按照建议使用,但它仍然无法编译\xe2\x80\x99t(请参阅下面的第二次编辑)。
#include "range/v3/all.hpp"\n#include "range/v3/iterator_range.hpp"\n\nclass LegacyIteratorWrapper {\npublic:\n using value_type = int;\n using difference_type = std::ptrdiff_t;\n using pointer = value_type*;\n using reference = value_type&;\n using iterator_category = std::input_iterator_tag;\n\n // The type isn\xe2\x80\x99t default-constructible, the error comes from here\n LegacyIteratorWrapper() = delete;\n\n static LegacyIteratorWrapper create();\n \n reference operator*() const;\n pointer operator->();\n LegacyIteratorWrapper& operator++();\n LegacyIteratorWrapper operator++(int);\n friend bool operator==(const LegacyIteratorWrapper& a, const LegacyIteratorWrapper& b);\n friend bool operator!=(const LegacyIteratorWrapper& a, const LegacyIteratorWrapper& b);\n};\n\nvoid foo()\n{\n LegacyIteratorWrapper begin { LegacyIteratorWrapper::create() };\n LegacyIteratorWrapper end { LegacyIteratorWrapper::create() };\n ranges::iterator_range<LegacyIteratorWrapper, LegacyIteratorWrapper> rng {begin, end};\n auto _ = rng\n | ranges::views::filter(\n [&](auto _) { return true; }\n )\n ;\n}\nRun Code Online (Sandbox Code Playgroud)\nIn file included from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/functional/reference_wrapper.hpp:24:0,\n from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/detail/variant.hpp:33,\n from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/iterator/common_iterator.hpp:26,\n from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/view/interface.hpp:24,\n from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/view/ref.hpp:25,\n from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/action/action.hpp:29,\n from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/action.hpp:17,\n from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/all.hpp:17,\n from <source>:1:\n/opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/functional/pipeable.hpp: In instantiation of \'constexpr auto ranges::operator|(Arg&&, Pipe) [with Arg = ranges::iterator_range<LegacyIteratorWrapper, LegacyIteratorWrapper>&; Pipe = ranges::views::view<ranges::make_pipeable_fn::operator()(Fun) const [with Fun = ranges::detail::bind_back_fn_<ranges::views::cpp20_filter_fn, foo()::<lambda(auto:15)> >]::_>; bool CPP_false_ = false; typename concepts::detail::identity<typename std::enable_if<(static_cast<bool>(((! is_pipeable_v<Arg>) && is_pipeable_v<Pipe>)) || CPP_false_), void>::type>::invoke<int> <anonymous> = 0]\':\n<source>:33:11: required from here\n/opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/functional/pipeable.hpp:63:53: error: no matching function for call to \'ranges::pipeable_access::impl<ranges::views::view<ranges::make_pipeable_fn::operator()(Fun) const [with Fun = ranges::detail::bind_back_fn_<ranges::views::cpp20_filter_fn, foo()::<lambda(auto:15)> >]::_> >::pipe(ranges::iterator_range<LegacyIteratorWrapper, LegacyIteratorWrapper>&, ranges::views::view<ranges::make_pipeable_fn::operator()(Fun) const [with Fun = ranges::detail::bind_back_fn_<ranges::views::cpp20_filter_fn, foo()::<lambda(auto:15)> >]::_>&)\'\n return pipeable_access::impl<Pipe>::pipe(static_cast<Arg &&>(arg), pipe);\n ^\nIn file included from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/range_fwd.hpp:22:0,\n from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/action/action.hpp:21,\n from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/action.hpp:17,\n from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/all.hpp:17,\n from <source>:1:\n/opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/view/view.hpp:114:35: note: candidate: template<class Rng, class Vw> static constexpr auto ranges::views::view<View>::pipe(Rng&&, Vw&&, concepts::detail::enable_if_t<concepts::detail::Nil, (static_cast<bool>((viewable_range<Rng> && invocable<View&, Rng>)) || concepts::detail::CPP_false(concepts::detail::Nil{}))>) [with Rng = Rng; Vw = Vw; View = ranges::make_pipeable_fn::operator()(Fun) const [with Fun = ranges::detail::bind_back_fn_<ranges::views::cpp20_filter_fn, foo()::<lambda(auto:15)> >]::_]\n static constexpr auto CPP_fun(pipe)(Rng && rng, Vw && v)( //\n ^\n/opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/view/view.hpp:114:35: note: template argument deduction/substitution failed:\n<source>: In function \'void foo()\':\n<source>:33:11: error: \'void _\' has incomplete type\n )\n ^\nASM generation compiler returned: 1\nIn file included from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/functional/reference_wrapper.hpp:24:0,\n from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/detail/variant.hpp:33,\n from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/iterator/common_iterator.hpp:26,\n from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/view/interface.hpp:24,\n from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/view/ref.hpp:25,\n from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/action/action.hpp:29,\n from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/action.hpp:17,\n from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/all.hpp:17,\n from <source>:1:\n/opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/functional/pipeable.hpp: In instantiation of \'constexpr auto ranges::operator|(Arg&&, Pipe) [with Arg = ranges::iterator_range<LegacyIteratorWrapper, LegacyIteratorWrapper>&; Pipe = ranges::views::view<ranges::make_pipeable_fn::operator()(Fun) const [with Fun = ranges::detail::bind_back_fn_<ranges::views::cpp20_filter_fn, foo()::<lambda(auto:15)> >]::_>; bool CPP_false_ = false; typename concepts::detail::identity<typename std::enable_if<(static_cast<bool>(((! is_pipeable_v<Arg>) && is_pipeable_v<Pipe>)) || CPP_false_), void>::type>::invoke<int> <anonymous> = 0]\':\n<source>:33:11: required from here\n/opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/functional/pipeable.hpp:63:53: error: no matching function for call to \'ranges::pipeable_access::impl<ranges::views::view<ranges::make_pipeable_fn::operator()(Fun) const [with Fun = ranges::detail::bind_back_fn_<ranges::views::cpp20_filter_fn, foo()::<lambda(auto:15)> >]::_> >::pipe(ranges::iterator_range<LegacyIteratorWrapper, LegacyIteratorWrapper>&, ranges::views::view<ranges::make_pipeable_fn::operator()(Fun) const [with Fun = ranges::detail::bind_back_fn_<ranges::views::cpp20_filter_fn, foo()::<lambda(auto:15)> >]::_>&)\'\n return pipeable_access::impl<Pipe>::pipe(static_cast<Arg &&>(arg), pipe);\n ^\nIn file included from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/range_fwd.hpp:22:0,\n from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/action/action.hpp:21,\n from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/action.hpp:17,\n from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/all.hpp:17,\n from <source>:1:\n/opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/view/view.hpp:114:35: note: candidate: template<class Rng, class Vw> static constexpr auto ranges::views::view<View>::pipe(Rng&&, Vw&&, concepts::detail::enable_if_t<concepts::detail::Nil, (static_cast<bool>((viewable_range<Rng> && invocable<View&, Rng>)) || concepts::detail::CPP_false(concepts::detail::Nil{}))>) [with Rng = Rng; Vw = Vw; View = ranges::make_pipeable_fn::operator()(Fun) const [with Fun = ranges::detail::bind_back_fn_<ranges::views::cpp20_filter_fn, foo()::<lambda(auto:15)> >]::_]\n static constexpr auto CPP_fun(pipe)(Rng && rng, Vw && v)( //\n ^\n/opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/view/view.hpp:114:35: note: template argument deduction/substitution failed:\n<source>: In function \'void foo()\':\n<source>:33:11: error: \'void _\' has incomplete type\n )\n ^\nExecution build compiler returned: 1\nRun Code Online (Sandbox Code Playgroud)\n编辑2(已解决):我收到错误,因为LegacyIteratorWrapper\xe2\x80\x99t 默认可构造。这是满足常规特征(由 range-v3 模拟)所必需的,这是 C++ 迭代器所要求的,并且包括默认可构造。
Nat*_*ica -2
在 range-v3 中,iterator_range您可以使用它将迭代器包装到范围对象中。
在 C++20 中,您可以使用std::span将这些迭代器包装到范围对象中