Перегрузить пользовательский компаратор в std::map

Я пытаюсь решить эту проблему. Я придумал это решение:

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

Как видно, это не компилируется: StockTicker::stocksDict не является статическим членом Теперь я не могу сделать это так, потому что мне может потребоваться несколько экземпляров StockTicker учебный класс.

std::map использует строгое определение параметра функции компаратора (std::map будет только передавать ключи для сравнения), поэтому я не могу перегрузить его, чтобы передать ссылку на текущий экземпляр StockTicker класс (который я мог бы использовать, чтобы получить доступ к StockTicker::stocksDict через публичных добытчиков)

Я черпал вдохновение из этого ТАКОГО вопроса и последующего ответа, чтобы сделать это:

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

Это тоже не скомпилируется. Я получаю такую ошибку в StockTicker::addOrUpdate() а также StockTicker::top() методы:error: '((StockTicker*)this)->StockTicker::stocksTicker' does not have class type,

Я тоже пробовал кучу других вещей (например, объявление метода публичного сравнения в StockTicker сам класс и пытается передать указатель на функцию std::map, Это также не удалось; StockTicker::stocksTicker объявляется раньше, чем метод компаратора, и компилятор жалуется).

Любые идеи о том, как это исправить?

1 ответ

Решение
 std::map<std::string, stockDictType::iterator, Comparator> stocksTicker(Comparator(stocksDict));

это определяет функцию-член с именем stocksTicker это занимает stocksDict аргумент типа Comparator и возвращает std::map,

std::map<std::string, stockDictType::iterator, Comparator> stocksTicker{Comparator{stocksDict}};

Это определяет переменную-член stocksTicker который по умолчанию инициализируется с Comparatorкоторый, в свою очередь, был инициализирован переменной-членом stocksDict,

Я полагаю, вы хотите второй.

Ваш синтаксис был на полпути между ними. Какой бы компилятор ты не запутал.

Живой пример

Вам следует StockTicker(StockTicker &&)=delete а также StockTicker& operator=(StockTicker &&)=delete, поскольку карты, содержащие ссылки на содержащий их класс, небезопасны для перемещения или копирования.

Создать эффективный ход здесь сложно. Я подозреваю, что соединение узлов C++17 может сделать это возможным. Возможно, вам придется встроить std::shared_ptr<stocksDict*> (да, общий указатель на указатель), и использовать .key_comp пересаживать stocksDict в цель.

Другие вопросы по тегам