Я пытаюсь решить Эта проблема. Я придумал это решение:
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
объявляется раньше, чем метод компаратора, и компилятор жалуется).
Любые идеи о том, как это исправить?
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
в цель.
Других решений пока нет …