我有一个Foo类,其中包含一个map并提供begin()end()函数对其进行迭代:

class Foo {
  typedef std::map<int, double> Container;
  typedef Container::const_iterator const_iterator;
  Container c_;
 public:
  const_iterator begin() const { return c_.begin(); }
  const_iterator end() const { return c_.end(); }
  void insert(int i, double d) { c_[i] = d; }
  // ...

};

现在,我想在内部将其从std::map<int, double>更改为std::set<int>,但是我不想破坏任何客户端代码。

因此double d函数中的insert现在将被忽略。以下代码仍应有效,其中it->second现在将始终始终为0.0:
Foo foo;
for(Foo::const_iterator it = foo.begin(); it != foo.end(); ++it) {
  std::cout << it->first << " " << it->second << std::endl;
}

如何在Foo类中进行这些更改?

换句话说,如何提供一个使新内部Foo::const_iterator适应旧std::set<int>::const_iterator行为的std::map<int,double>::const_iterator

更新:我想摆脱map的原因是内存效率。我有数百万个Foo实例,并且无法在其中存储double值。

最佳答案

将使用

std::set<std::pair<int, double> >

这样的可比性还不够吗?

否则,您总是可以编写自己的迭代器,该迭代器包装std::list迭代器并提供firstsecond成员。基本上,您的operator++会在真正的迭代器等上调用operator++,并且取消引用的运算符可以返回临时std::pair(按值)或对存在于迭代器本身中的std::pair的引用(如果您使用的是旧版)代码可以处理)。

更新(略作虚构的示例)可能会根据您的方案而起作用:
#include <iostream>
#include <set>

class Foo {
  typedef std::set<int> Container;
  typedef Container::const_iterator legacy_iterator;
  Container c_;

  // legacy iterator doesn't have a virtual destructor (probably?), shouldn't
  // be a problem for sane usage though
  class compat_iterator : public legacy_iterator {
  public:
     compat_iterator(const legacy_iterator& it) : legacy_iterator(it) {
     }

     const std::pair<int,double> *operator->() const {
        static std::pair<int,double> value;
        value = std::make_pair(**this, 0.0);
        // Not meeting the usual semantics!
        return &value;
     }
  };
 public:
  typedef compat_iterator const_iterator;

  const_iterator begin() const { return c_.begin(); }
  const_iterator end() const { return c_.end(); }

};



int main() {

  Foo foo;
  for(Foo::const_iterator it = foo.begin(); it != foo.end(); ++it) {
     std::cout << it->first << " " << it->second << std::endl;
  }

}

10-06 13:51
查看更多