How to adapt a set iterator to behave like a map iterator?

I have a class Foothat contains mapand provides functions begin()and end()to iterate through it:

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

};

Now I would like to change it inside std::map<int, double>only to std::set<int>, but I do not want to break the client code.

So, double dthe function is insertnow simply ignored. And the following code should remain valid where it->secondit will always be 0.0:

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

How can I make these changes to the class Foo?

In other words, how can I provide Foo::const_iteratorthat adapts the new inner std::set<int>::const_iteratorto behave like the old std::map<int,double>::const_iterator?

: , map, - . Foo double .

+5
5

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

?

, std:: list first second. ++ ++ .., - std:: ( ), std:: , ( ).

, , :

#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;
  }

}
+2

- ?

#include <iostream>
#include <map>
#include <set>

struct Funky
{
    int first;
    static const double second;

    Funky(int i)
    :   first(i)
    {}
};

const double Funky::second = 0.0;

bool operator<(const Funky& lhs, const Funky& rhs)
{
    return lhs.first < rhs.first;
}

class Foo
{
private:
    //std::map<int,double> m_data;
    std::set<Funky> m_data;
public:
    //typedef std::map<int,double>::const_iterator const_iterator;
    typedef std::set<Funky>::const_iterator const_iterator;

    const_iterator begin() const
    {
        return m_data.begin();
    }

    const_iterator end() const
    {
        return m_data.end();
    }

    void insert(int i, double d)
    {
        //m_data.insert(std::make_pair(i, d));
        m_data.insert(i);
    }
};

int main()
{
    Foo foo;
    foo.insert(23, 9.0);
    for(Foo::const_iterator it=foo.begin(), iend=foo.end(); it!=iend; ++it)
    {
        std::cout << it->first << ' ' << it->second << '\n';
    }
    return 0;
}
+1

, -

operator int()(const std::pair<int, double>& p) const {
    return p.first;
}

?

0

, fake_pair, first second set<fake_pair> Foo.

0

You cannot, not completely. The problem is that you are changing your interface, which will always break your customers. I would recommend you create two new functions newBegin and newEnd (or similar) that have your new behavior. In your old interface, you keep this, but mark it as depreciated. Implementing this old interface may use one of the works described by others.

0
source

All Articles