如何避免为模板化迭代器的每个可能的实例化特化iterator_traits?

时间:2018-05-23 19:31:54

标签: c++ c++11 iterator iterator-traits

我想在基于for循环的基于范围的情况下进行pimp,例如通过启用反转iteraton。我设法通过编写适配器在某种程度上使它工作,但我迷失了如何使adpaptor可组合。

#include <iostream>
template <typename IT> struct reversed_range {
        struct reversed_iterator {
            IT it;
            reversed_iterator(IT it): it(it){}
            reversed_iterator& operator++(){
                --it;
                return (*this);
            }
            typename std::iterator_traits<IT>::reference operator*(){
                IT tmp = it;
                --tmp;
                return *tmp;
            }
            bool operator==(const reversed_iterator& other) const {
                return it == other.it;
            }
            bool operator!=(const reversed_iterator& other) const { 
                return !(*this == other);
            }
        };
        IT itbegin;
        IT itend;
        reversed_range(const IT& b,const IT& e): itbegin(b),itend(e){}
        reversed_iterator begin() const { return reversed_iterator(itend); }
        reversed_iterator end() const { return reversed_iterator(itbegin); }
    };
    template <typename IT>
    reversed_range<IT> reverse_range(const IT& begin,const IT& end) { 
        return reversed_range<IT>(begin,end); 
    }
    template <typename C>
    reversed_range<C> reverse_range(const C& c) {
        return reversed_range<typename C::iterator>(std::begin(c),std::end(c));
    }

int main() {
    int x[] = {1,2,3,4,5};
    for (auto y : reverse_range(std::begin(x),std::end(x))){
        std::cout << y << "\t";
    }
    for (auto y : reverse_range(reverse_range(std::begin(x),std::end(x)))){
        std::cout << y << "\t";
    }
    return 0;
}

第一个循环就像一个魅力,但第二个循环我得到错误:

error: no type named ‘reference’ in ‘struct std::iterator_traits<reversed_range<int*> >’
             typename std::iterator_traits<IT>::reference operator*(){
                                                          ^~~~~~~~

我知道为什么会发生这种情况,我知道如何解决这个特殊情况。但是,如果我正确理解this answer,我必须对iterator_traits的每个可能的实例化进行专门化reversed_iterator,这是不可行的。我有点迷失,大部分时间我都在编写自己的迭代器,我发现自己编写了大量的样板文件,只是为了达到一个点,我意识到我需要指数级的样板才能让它工作。我的意思是我甚至没有开始考虑const_iterator s。

有没有办法让上述工作正常工作(而不必为我想要反转的iterator_traits专门化iterator

PS:标记为C ++ 11,因为这是我目前的范围,但如果有相应的改进,我不介意使用更新的标准。

1 个答案:

答案 0 :(得分:3)

默认情况下

std::iterator_traits<Iterator>::something is simply Iterator::something。因此,只需将typedef添加到reversed_iterator类型中:

struct reversed_iterator {
    using difference_type = typename std::iterator_traits<IT>::difference_type;
    using value_type = typename std::iterator_traits<IT>::value_type;
    using pointer = typename std::iterator_traits<IT>::pointer;
    using reference = typename std::iterator_traits<IT>::reference;
    using iterator_category = /* appropriate category */;

    // ...
};