简体   繁体   English

如何将一对迭代器转换为视图?

[英]How to convert a pair of iterator into a view?

I have a pair of iterator, and I would like to use ranges::views::filter(some_predicate) on it (with the pipe operator).我有一对迭代器,我想在它上面使用ranges::views::filter(some_predicate) (使用 pipe 运算符)。 AFAIU I should first convert my pair of iterator into a view. AFAIU 我应该首先将我的一对迭代器转换成一个视图。 I tried to use ranges::subrange(first, last) to do so, but I'm getting horrible error messages.我尝试使用ranges::subrange(first, last)这样做,但我收到了可怕的错误消息。

Note1: I'm using C++14 and range-v3 version 0.9.1 (the last version compatible with gcc-5.5).注意 1:我使用的是 C++14 和 range-v3 版本 0.9.1(与 gcc-5.5 兼容的最后一个版本)。 If the solution differs when using C++17/20 and/or when using C++20 std::ranges, I'm also interested to know what changed.如果在使用 C++17/20 和/或使用 C++20 std::ranges 时解决方案有所不同,我也很想知道发生了什么变化。

Note2: I find the documentation of range-v3 severely lacking, so I'm using cppreference.com .注2:我发现 range-v3 的文档严重缺乏,所以我使用cppreference.com If you know a better documentation, I'm very interested.如果你知道更好的文档,我很感兴趣。


EDIT:编辑:

In my real code, I'm wrapping a java-style legacy iterator (that has a next() method instead of operator++ / operator* . I'm wrapping them in a C++-compatible wrapper. Then I tried to convert that wrapper into a view, and finally filter it. I reproduce a minimal example on godbolt . This use iterator_range as suggested, but it still doesn't compile (see the second edit below).在我的真实代码中,我包装了一个 java 风格的遗留迭代器(它有一个next()方法而不是operator++ / operator* 。我将它们包装在一个与 C++ 兼容的包装器中。然后我尝试将该包装器转换为一个视图,最后过滤它。我在godbolt上复制了一个最小的例子。按照建议使用iterator_range ,但它仍然无法编译(参见下面的第二个编辑)。

#include "range/v3/all.hpp"
#include "range/v3/iterator_range.hpp"

class LegacyIteratorWrapper {
public:
    using value_type = int;
    using difference_type = std::ptrdiff_t;
    using pointer = value_type*;
    using reference = value_type&;
    using iterator_category = std::input_iterator_tag;

    // The type isn’t default-constructible, the error comes from here
    LegacyIteratorWrapper() = delete;

    static LegacyIteratorWrapper create();
    
    reference operator*() const;
    pointer operator->();
    LegacyIteratorWrapper& operator++();
    LegacyIteratorWrapper operator++(int);
    friend bool operator==(const LegacyIteratorWrapper& a, const LegacyIteratorWrapper& b);
    friend bool operator!=(const LegacyIteratorWrapper& a, const LegacyIteratorWrapper& b);
};

void foo()
{
    LegacyIteratorWrapper begin { LegacyIteratorWrapper::create() };
    LegacyIteratorWrapper end { LegacyIteratorWrapper::create() };
    ranges::iterator_range<LegacyIteratorWrapper, LegacyIteratorWrapper> rng {begin, end};
    auto _ = rng
        | ranges::views::filter(
            [&](auto _) { return true; }
          )
        ;
}
In file included from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/functional/reference_wrapper.hpp:24:0,
                 from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/detail/variant.hpp:33,
                 from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/iterator/common_iterator.hpp:26,
                 from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/view/interface.hpp:24,
                 from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/view/ref.hpp:25,
                 from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/action/action.hpp:29,
                 from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/action.hpp:17,
                 from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/all.hpp:17,
                 from <source>:1:
/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]':
<source>:33:11:   required from here
/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)> >]::_>&)'
             return pipeable_access::impl<Pipe>::pipe(static_cast<Arg &&>(arg), pipe);
                                                     ^
In file included from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/range_fwd.hpp:22:0,
                 from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/action/action.hpp:21,
                 from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/action.hpp:17,
                 from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/all.hpp:17,
                 from <source>:1:
/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)> >]::_]
             static constexpr auto CPP_fun(pipe)(Rng && rng, Vw && v)( //
                                   ^
/opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/view/view.hpp:114:35: note:   template argument deduction/substitution failed:
<source>: In function 'void foo()':
<source>:33:11: error: 'void _' has incomplete type
           )
           ^
ASM generation compiler returned: 1
In file included from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/functional/reference_wrapper.hpp:24:0,
                 from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/detail/variant.hpp:33,
                 from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/iterator/common_iterator.hpp:26,
                 from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/view/interface.hpp:24,
                 from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/view/ref.hpp:25,
                 from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/action/action.hpp:29,
                 from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/action.hpp:17,
                 from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/all.hpp:17,
                 from <source>:1:
/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]':
<source>:33:11:   required from here
/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)> >]::_>&)'
             return pipeable_access::impl<Pipe>::pipe(static_cast<Arg &&>(arg), pipe);
                                                     ^
In file included from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/range_fwd.hpp:22:0,
                 from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/action/action.hpp:21,
                 from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/action.hpp:17,
                 from /opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/all.hpp:17,
                 from <source>:1:
/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)> >]::_]
             static constexpr auto CPP_fun(pipe)(Rng && rng, Vw && v)( //
                                   ^
/opt/compiler-explorer/libs/rangesv3/0.9.1/include/range/v3/view/view.hpp:114:35: note:   template argument deduction/substitution failed:
<source>: In function 'void foo()':
<source>:33:11: error: 'void _' has incomplete type
           )
           ^
Execution build compiler returned: 1

EDIT2 (SOLVED): I got an error because LegacyIteratorWrapper isn't default constructible. EDIT2(已解决):我收到一个错误,因为LegacyIteratorWrapper不是默认可构造的。 This is required to satisfy the regular trait (emulated by range-v3), which is required by C++ iterator, and which include being default-constructible.这是满足常规特征(由 range-v3 模拟)所必需的,这是 C++ 迭代器所要求的,其中包括可默认构造。

I have a pair of iterator, and I would like to use ranges::views::filter(some_predicate) on it (with the pipe operator).我有一对迭代器,我想在它上面使用ranges::views::filter(some_predicate) (使用 pipe 运算符)。 AFAIU I should first convert my pair of iterator into a view. AFAIU 我应该首先将我的一对迭代器转换成一个视图。 I tried to use ranges::subrange(first, last) to do so, but I'm getting horrible error messages.我尝试使用ranges::subrange(first, last)这样做,但我收到了可怕的错误消息。

Since you haven't really given a code backing up your getting horrible error messages , here's a code that defines two iterators on a vector, makes use of ranges::subrange , and filters the resulting range.由于您还没有真正提供代码来支持您收到可怕的错误消息,因此这里有一个代码,它在向量上定义了两个迭代器,使用了ranges::subrange并过滤了结果范围。

#include <iostream>
#include <range/v3/view/filter.hpp>
#include <range/v3/view/subrange.hpp>
#include <vector>

namespace r = ranges;
namespace rv = ranges::views;

int main() {
    std::vector<int> v{1,2,3,4,5};
    auto even = [](auto x){ return x % 2 == 0; };
    auto i1 = v.begin() + 1;
    auto ie = v.end() - 1;
    auto w = r::subrange(i1, ie) | rv::filter(even);
    for (auto i : w) {
        std::cout << i << std::endl;
    }
}

If you clarify what your sample code is and what the errors you get, I or someone else could be able to give you a better answer.如果你澄清的示例代码是什么以及你得到了什么错误,我或其他人可以给你一个更好的答案。

In ranges-v3, there is iterator_range which you can use to wrap the iterators into a range object.在 range-v3 中,您可以使用iterator_range将迭代器包装到 object 范围内。

In C++20, you can use std::span to wrap those iterators into an range object在 C++20 中,您可以使用std::span将这些迭代器包装到一个范围 object

You can convert each pair of equal Iterators to a std::ranges::subrange with:您可以将每对相等的迭代器转换为std::ranges::subrange

auto my_range = std::ranges::subrange{begi,endi};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM