首页 文章

仅覆盖C映射迭代器解除引用

提问于
浏览
3

我有以下类包装C映射 . 我只是'd like to override just the iterator dereference, to return the map'的值而不是键 . 这有可能,而不必重新实现整个 std::map 迭代器(我应该尽可能避免)吗?

这里是:

#include <map>

using std::map;

class X {
    using Type = map<int, double>;
    using const_iterator = typename Type::const_iterator;

  public:

    void insert(int key, double value) {
        my_map[key] = value;
    }

    const_iterator cbegin() const { return my_map.cbegin(); }

    const_iterator cend() const { return my_map.cend(); }

    const_iterator begin() const { return my_map.cbegin(); }

    const_iterator end() const { return my_map.cend(); }

  private:
    Type my_map;
};

int main() {
    X x;
    double i;
    for (const auto& it : x) {
        i = it.second; // works
        i = it; // fails
    }
}

2 回答

  • 1

    您几乎需要实现整个迭代器类型以提供新的迭代器行为 . 幸运的是,Boost有一些工具可以使这更容易:boost::iterator_facade是一个创建迭代器类型的工具,它负责满足标准定义的各种类型迭代器的所有需求细节 . 对于你想要创建一个包装另一个迭代器的迭代器的常见情况,只覆盖它的一部分功能,那就是boost::iterator_adaptor .

    所以你可以像这样定义你的 X::const_iterator

    #include <map>
    #include <boost/iterator_adaptor.hpp>
    
    using std::map;
    
    class X {
        using Type = map<int, double>;
    public:
        class const_iterator : public boost::iterator_adaptor<
            const_iterator,                 // Derived iterator type, for CRTP
            typename Type::const_iterator,  // Wrapped iterator type
            const double>                   // Value type
        {
        public:
            const_iterator() {}
        private:
            // Allow X to create X::const_iterator from Type::const_iterator:
            explicit const_iterator(typename Type::const_iterator map_iter)
                : iterator_adaptor(map_iter) {}
            friend X;
    
            // Define the dereference operation:
            const double& dereference() const
            { return base()->second; }
            // Allow boost's internals to use dereference():
            friend boost::iterator_core_access;
        };
    
        const_iterator cbegin() const { return const_iterator(my_map.cbegin()); }
    };
    

    ...

    (我故意将名称 X::const_iterator 的访问权限从私有更改为公共 . 有人可能想要明确命名迭代器类型 . )

  • 0

    借用Yakk的回答here,您可以轻松修改它以满足您的需求 .

    template<class T>
    T value_of(T t) { return std::move(t); }
    template<class K, class V>
    V value_of(std::pair<K, V> const& p) { return p.second; }
    
    template<class It>
    struct range_t {
        It b;
        It e;
        It begin() const { return b; }
        It end() const { return e; }
    };
    
    template<class T>
    struct value_t {
        T t;
        void operator++(){ t++; }
        auto operator*() { return value_of(*t); }
        friend bool operator==(value_t const& left, value_t const& right)
        { return left.t == right.t; }
        friend bool operator!=(value_t const& left, value_t const& right)
        { return left.t != right.t; }
    };
    
    template<class T>
    range_t<value_t<T>> values_over(T b, T e) {
        return {{b}, {e}};
    }
    
    template<class C>
    auto values_of(C& c) {
        using std::begin; using std::end;
        return values_over(begin(c), end(c));
    }
    
    int main() {
        X x;
        double i;
        for (double const& it : values_of(x)) {
            i = it;
        }
    }
    

相关问题