将自定义比较器重载到 std::map

Overload custom comparator to std::map

我正在尝试解决 this problem。我想到了这个解决方案:

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 class 的多个实例。

std::map使用严格的比较器函数参数定义(std::map只会传入要比较的键),所以我不能重载它来传递对当前实例的引用StockTicker class(我本可以通过 public getter 访问 StockTicker::stocksDict

我从 and the 中得到灵感来做这个:

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() 方法中得到这个 kind of errorerror: '((StockTicker*)this)->StockTicker::stocksTicker' does not have class type.

我也尝试了很多其他的东西(比如在 StockTicker class 本身中声明一个 public 比较器方法,并试图将它的函数指针传递给 std::map。那也失败了;StockTicker::stocksTicker 在比较器方法声明之前被声明,编译器抱怨)。

关于如何解决这个问题有什么想法吗?

 std::map<std::string, stockDictType::iterator, Comparator> stocksTicker(Comparator(stocksDict));

这定义了一个名为 stocksTicker 的成员函数,它接受一个 stocksDict 类型的参数 Comparator 和 returns 一个 std::map.

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

这定义了一个成员变量stocksTicker,默认情况下,它用Comparator初始化,而Comparator又用成员变量stocksDict.

初始化

我假设你想要第二个。

你的语法介于两者之间。无论您对此感到困惑的编译器是什么。

Live example

您应该 StockTicker(StockTicker &&)=deleteStockTicker& operator=(StockTicker &&)=delete,因为包含对其 class 的引用的地图移动或复制是不安全的。

在这里生成有效的移动是很棘手的。我怀疑 C++17 节点拼接可能使它成为可能。您可能必须嵌入一个 std::shared_ptr<stocksDict*>(是的,一个指向指针的共享指针),并使用 .key_comp 重新设置目标中的 stocksDict