调整自定义迭代器,以便(a?)reverse_iterator可以翻转它的输出

use*_*035 6 c++ iterator

最近,用户@Mooing Duck设计concatenated_range了一个优雅的自定义迭代器,解决了"链接"两个迭代器的问题.

它适用于它的预期用途:

auto range0=concatenate_ranges(x,x+i-1,x+i,x+a5+1);
a6=foo(range0.first,range0.second); 
Run Code Online (Sandbox Code Playgroud)

现在,我想通过做(示例#2)来适应它:

auto range0=concatenate_ranges(x+a5+1,x+i-1,x+i+1,x+n);
a6=foo(std::reverse_iterator<float*>(range0.second),std::reverse_iterator<float*>(range0.first));
Run Code Online (Sandbox Code Playgroud)

毋庸置疑,编译器并不开心.另一种选择(不确定订购是否在这里):

auto range0=concatenate_ranges(std::reverse_iterator<float*>(x+n),x+i+1,x+i-1,std::reverse_iterator<float*>(x+a5[i]+1));
a6=foo(range0.first,range0.second);
Run Code Online (Sandbox Code Playgroud)

不被认为是理所当然的:(.

我的问题是:我怎样才能适应concatenate_ranges()它的输出可以输入std::reverse_iterator(如上面的第二个例子).另外,boost::如果它让事情变得更容易,我不介意使用.

编辑:

用户@Jack报告原始答案中的链接不显示他的代码.我不知道这个问题有多普遍,所以为了清楚起见,我重现了我在这里提到的代码(请参考原始答案的解释):

#include <boost/iterator/iterator_facade.hpp>
#include <iterator>
#include <cassert>

template<class base>
class concatenated_range_iterator 
    : public boost::iterator_facade<
        concatenated_range_iterator<base>,
        typename std::iterator_traits<base>::value_type,
        typename std::iterator_traits<base>::iterator_category,
        typename std::iterator_traits<base>::reference,
        typename std::iterator_traits<base>::difference_type
        >
{
public:
    typedef typename std::iterator_traits<base>::iterator_category iterator_category;
    typedef typename std::iterator_traits<base>::value_type        value_type;
    typedef typename std::iterator_traits<base>::difference_type   difference_type;
    typedef typename std::iterator_traits<base>::pointer           pointer;
    typedef typename std::iterator_traits<base>::reference         reference;

    concatenated_range_iterator() = default;
    concatenated_range_iterator(bool begin, base begin1, base end1, base begin2, base end2) 
        :current(begin?begin1:end2), end_first(end1), begin_second(begin2), in_first(begin)
        {}

    reference dereference() {return *current;}
    reference dereference() const {return *current;}
    bool equal(const concatenated_range_iterator& rhs) const {
        assert(end_first==rhs.end_first);
        assert(begin_second==rhs.begin_second);
        return in_first==rhs.in_first && current==rhs.current;
    }
    void increment() {
        ++current;
        if (in_first) {
            if (current==end_first) {
                current = begin_second;
                in_first = false;
            }
        } 
    }
    void decrement() {
        if (!in_first) {
            if (current==begin_second) {
                current = end_first;
                in_first = true;
            }
        }
        --current;
    }
    void advance(difference_type n) {
        if (n>=0) {
            if (in_first) {
                difference_type safe = end_first-current;
                if (safe <= n) {
                    current = begin_second;
                    n -= safe;
                    in_first = false;
                }
            }
        } else {
            if (!in_first) {
                difference_type safe = current-begin_second;
                if (safe <= n) {
                    current = end_first;
                    n += safe;
                    in_first = true;
                }
            }
        }
        current += n;
    }
    difference_type distance_to(const concatenated_range_iterator& rhs) const {
        assert(end_first==rhs.end_first);
        assert(begin_second==rhs.begin_second);
        if (in_first) {
            if (rhs.in_first) 
                return rhs.current-current;
            else
                return rhs.current-begin_second + end_first-current;
        } else {
            if (rhs.in_first) 
                return rhs.current-end_first + begin_second-current;
            else
                return rhs.current-current;
        }
    }
protected:
    base current; 
    base end_first;
    base begin_second;
    bool in_first;
};
template<class base>
std::pair<concatenated_range_iterator<base>,concatenated_range_iterator<base>>
    concatenate_ranges(base first1, base end1, base first2, base end2)
{
    return std::pair<concatenated_range_iterator<base>,concatenated_range_iterator<base>>(
        concatenated_range_iterator<base>(true, first1, end1, first2, end2),
        concatenated_range_iterator<base>(false, first1, end1, first2, end2)
        );
}


#include <vector>
#include <iostream>
int main() {
    std::vector<int> vars = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

    auto range = concatenate_ranges(vars.begin(), vars.begin()+4, vars.begin()+5, vars.end());
    for(auto iter=range.first; iter!=range.second; ++iter)
        std::cout << *iter << ' ';
}
Run Code Online (Sandbox Code Playgroud)

n. *_* m. 5

您正在reverse_iterator错误地实例化模板.尝试

auto fst = std::reverse_iterator<decltype(range0.second)>(range0.second);
auto snd = std::reverse_iterator<decltype(range0.first)>(range0.first);
Run Code Online (Sandbox Code Playgroud)

要使类型更明确:

typedef std::vector<int>::iterator VI;
typedef concatenated_range_iterator<VI> CRVI;
typedef std::pair<CRVI, CRVI> CRVIrange;
CRVIrange range0 = concatenate_ranges(vars.begin(), vars.begin()+2,
                                       vars.begin()+5, vars.end());

typedef std::reverse_iterator<CRVI> RCRVI;
RCRVI fst = RCRVI(range0.second);
RCRVI snd = RCRVI(range0.first);
Run Code Online (Sandbox Code Playgroud)

我不想写下类似的东西std::pair<std::reverse_iterator<concatenated_range_iterator<std::vector<int>::iterator>>,std::reverse_iterator<concatenated_range_iterator<std::vector<int>::iterator>>>!