代码之家  ›  专栏  ›  技术社区  ›  463035818_is_not_an_ai

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

  •  3
  • 463035818_is_not_an_ai  · 技术社区  · 6 年前

    我想为循环增加我的范围,例如通过启用反向迭代。我写了一个适配器,在某种程度上使它工作起来,但是我在如何使ADAPTAtor可组合上迷失了方向。

    #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 我想倒车吗?

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

    1 回复  |  直到 6 年前
        1
  •  3
  •   Justin    6 年前

    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 */;
    
        // ...
    };