std::map 使用自定义密钥

std::map with custom key

我想使用具有以下自定义键的标准地图:

struct ParserKey{
    ParserKey(uint16_t compno,
             uint8_t resno,
             uint64_t precinctIndex) : compno_(compno),
                                       resno_(resno),
                                       precinctIndex_(precinctIndex)
    {
    }
     uint16_t compno_;
     uint8_t resno_;
     uint64_t precinctIndex_;
};

不过,没有明显的键排序方式。 可以订购这些键,还是我需要不同的关联集合?

您可以按照与 std::lexicographical_compare 相同的方式对这些整数强加任意总顺序。

所以,偷懒的做法是:

// inside ParserKey ...

std::array<std::uint16_t,3> to_array() const {
  return {compno_, resno_, precinctIndex_};
}

friend bool operator<(ParserKey const& lhs, ParserKey const& rhs) {
  auto const l = lhs.to_array();
  auto const r = rhs.to_array();
  return std::lexicographical_compare(begin(l),end(l), begin(r), end(r));
}

但它带来了将成员压入可迭代容器的开销。如果您不想要那样,您可能必须自己重新实现一个字典序比较。

如果您不关心具体的顺序,只想满足排序的要求,一个常见且简单的模式是将 std::tie 与所有 class 成员一起使用比较实例,然后比较这些结果。

std::tie 创建对成员的引用的 std::tuplestd::tuple 实现 operator< 按字典顺序比较其元素(在本例中为对象的成员) .

在你的情况下,使用成员 operator< :

bool operator<(const ParserKey & other) const
{
    return std::tie(compno_, resno_, precinctIndex_) < 
        std::tie(other.compno_, other.resno_, other.precinctIndex_);
}

实例https://godbolt.org/z/v433v54jz

在 C++20 中,您可以这样做:(在 class 范围内)

friend auto operator<=>(const ParserKey &, const ParserKey &) = default;

别忘了#include <compare>

这将为您提供所有 6 个关系运算符:==!=<<=>>=、执行词典比较(与@FrançoisAndrieux 的回答相同)。