仅覆盖C ++映射迭代器取消引用

时间:2018-12-10 02:34:15

标签: c++

我有以下包装C ++映射的类。我只想覆盖迭代器取消引用,只返回映射的值而不是键。完全有可能,而不必重新实现整个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 个答案:

答案 0 :(得分: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的访问权限从私有更改为公共。有人可能希望显式命名该迭代器类型。)

答案 1 :(得分: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;
    }
}