vendredi 31 mars 2017

Overload custom comparator to std::map

I am trying to solve this problem. I came up with this solution:

typedef unordered_map<string, double> stockDictType;

class StockTicker {
  class Comparator {
  public:
    inline bool operator() (const string &a, const string &b) const {
      return stocksDict.at(a) < stocksDict.at(b);
    }
  };

  stockDictType stocksDict;

  map<string, stockDictType::iterator, Comparator> stocksTicker; // this is where I need a custom comparator method

  int tickerSize;

public:
  StockTicker(int k): tickerSize(k) {}

  // some other methods
};

As is evident, this fails to compile: StockTicker::stocksDict is not a static member. Now I can't make it so because I could require multiple instances of the StockTicker class.

std::map uses a strict comparator function parameter definition (std::map will only pass in the keys to be compared), so I can't overload it to pass a reference to the current instance of the StockTicker class (which I could've used to get access to StockTicker::stocksDict through public getters)

I took inspiration from this SO question and the subsequent answer to do this:

typedef unordered_map<string, double> stockDictType;

class StockTicker {
  class Comparator {
  public:
    stockDictType &_stockDictRef;

    explicit Comparator(stockDictType &stocksDict): _stockDictRef(stocksDict) {}

    inline bool operator() (const string &a, const string &b) const {
      return _stockDictRef.at(a) < _stockDictRef.at(b);
    }
  };

  stockDictType stocksDict;
  map<string, stockDictType::iterator, Comparator> stocksTicker(Comparator{stocksDict});
  int tickerSize;

public:
  StockTicker(int k): tickerSize(k) {}

  void addOrUpdate(string name, double price) {
    stocksDict[name] = price;
    stocksTicker.at(name) = stocksDict.find(name);
  }

  vector<stockDictType::iterator> top() {
    vector<stockDictType::iterator> ret(tickerSize);

    auto it = stocksTicker.begin();
    for(int i = 0; i < tickerSize; i++, it++)
      ret[i] = it->second;

    return ret;
  }
};

This won't compile either. I get this kind of error in the StockTicker::addOrUpdate() and StockTicker::top() methods: error: '((StockTicker*)this)->StockTicker::stocksTicker' does not have class type.

I tried a bunch of other stuff too (like declaring a public comparator method in the StockTicker class itself and trying to pass a function pointer of it to std::map. That failed as well; StockTicker::stocksTicker gets declared before the comparator method does and the compiler complains).

Any ideas on how to go about fixing this?

Aucun commentaire:

Enregistrer un commentaire