使可互换的前向/后向范围迭代器成为可能

时间:2016-11-11 08:55:53

标签: c++ c++14

我希望能够以简单的for (const auto& item : collection)样式以相反的顺序迭代集合(我只会在向量上执行此操作,如果这很重要),我发现这个答案完美无缺:{{3} }。但后来我希望能够向前或向后迭代,所以我修改了代码,如下所示:

#include <iterator>
#include <iostream>
#include <vector>

template <typename T>
struct reversable_wrapper {
    T& iterable;
    bool reverse;

    reversable_wrapper(T&& iterable) : reversable_wrapper(iterable, true) {};
    reversable_wrapper(T&& iterable, bool reverse) : iterable(iterable), reverse(reverse) {};
};

template <typename T>
auto std::begin (reversable_wrapper<T> w)
{
    if (w.reverse) return std::rbegin(w.iterable);
    else return std::begin(w.iterable);
}

template <typename T>
auto std::end (reversable_wrapper<T> w)
{
    if (w.reverse) return std::rend(w.iterable);
    else return std::end(w.iterable);
}

template <typename T>
reversable_wrapper<T> reverse (T&& iterable) { return reversable_wrapper<T>(iterable); }

template <typename T>
reversable_wrapper<T> forward (T&& iterable) { return reversable_wrapper<T>(iterable, false); }

int main()
{
    std::vector<int> vec = {1,2,3};
    for (const auto& i : reverse(vec)) std::cout<<i<<std::endl;
    return 0;
}

基本上,我想要实现的是for (const auto& item : cond ? forward(coll) : reverse(coll))。但是,此代码会出现以下错误:

> $ g++ -std=c++14 iterators.cpp -o iterators
iterators.cpp: In instantiation of ‘auto std::begin(reversable_wrapper<T>) [with T = std::vector<int>&]’:
iterators.cpp:37:37:   required from here
iterators.cpp:18:38: error: inconsistent deduction for ‘auto’: ‘std::reverse_iterator<__gnu_cxx::__normal_iterator<int*, std::vector<int> > >’ and then ‘__gnu_cxx::__normal_iterator<int*, std::vector<int> >’
     else return std::begin(w.iterable);
                                      ^
iterators.cpp: In instantiation of ‘auto std::end(reversable_wrapper<T>) [with T = std::vector<int>&]’:
iterators.cpp:37:37:   required from here
iterators.cpp:25:36: error: inconsistent deduction for ‘auto’: ‘std::reverse_iterator<__gnu_cxx::__normal_iterator<int*, std::vector<int> > >’ and then ‘__gnu_cxx::__normal_iterator<int*, std::vector<int> >’
     else return std::end(w.iterable);

我无法确定可以向std::beginstd::end提供哪个签名来克服此问题,如果可以的话。

我正在使用g ++ 5.4.0。

1 个答案:

答案 0 :(得分:0)

您的问题是,您尝试从函数中返回std::vector::iteratorstd::vector::reverse_iterator中的一个。可悲的是,这些是不相关的类型。

我认为你唯一的机会就是写一个reversible_iterator_wrapper来保存这两种类型,并将其参数转发给正确的参数。这将是乏味的。最简单(但不是最有效)的选项可能涉及虚函数!