【问题标题】:Writing a custom comparator for a C++ map which has a custom defined key为具有自定义键的 C++ 映射编写自定义比较器
【发布时间】:2018-10-04 05:41:38
【问题描述】:

我正在尝试为具有自定义键的 C++ 映射编写自定义比较器。

struct key { int year; int no; };
map<key, detail, compare> details_map;

如果year 值相等,则必须比较no 值。

我试图找出一种方法来编写一个可以比较两个值的比较器。到目前为止,我只能编写一个比较一个值的比较器。

struct Compare{bool operator()(const key &lhs,const key &rhs)const{return lhs.year<rhs.year;}}

有人可以解释一下比较器在map 中的工作原理吗?

另外,是否可以将比较器写成函数?

【问题讨论】:

  • 使用条件运算符比较多个值,就像在普通函数中所做的那样。
  • 在 c++ 中它与在 Java 中不同。在 c++ 中,比较器实际上是“少运算符”,而在 Java 中,它是 3 路比较。 C++ 中的类比是“操作员飞船”,但它只是从 c++ 20 开始,并且 std::map 仍然期望将“操作员少”作为比较模板参数。

标签: c++ comparator


【解决方案1】:

在您的operator() 中,如果year 值相等,则只需比较no 值:

struct Compare {
    bool operator()(const key &lhs, const key &rhs) const {
        if (lhs.year == rhs.year) {
            return lhs.no < rhs.no;
        }
        return lhs.year < rhs.year;
    }
};

是的,比较器可以作为一个独立的函数来实现:

bool Compare (const key &lhs, const key &rhs) {
    if (lhs.year == rhs.year) {
        return lhs.no < rhs.no;
    }
    return lhs.year < rhs.year;
}

或者,您可以让比较器使用std::tie() 来比较您的关键字段。见@Jarod42's answer

不过,为您的 key 类型实现 operator&lt; 会更有意义:

struct key {
    int year;
    int no;

    bool operator<(const key &rhs) const {
        if (year == rhs.year) {
            return no < rhs.no;
        }
        return year < rhs.year;
    }
};

或者

struct key {
    int year;
    int no;
};

bool operator<(const key &lhs, const key &rhs) {
    if (lhs.year == rhs.year) {
        return lhs.no < rhs.no;
    }
    return lhs.year < rhs.year;
}

那么你就不需要单独的比较器了:

map<key, detail> details_map;

【讨论】:

  • @ÖöTiib 其实我在想std::tie(),直到看到Jarod 的回答才想起来
  • 从您的解决方案中,我们可以使用这 1 行代码“if(details_map.find(key_1)!= details_map.end())”在地图中搜索一个键吗?或者我们是否需要编写任何新函数来比较这种情况下的键? -- 谢谢。
  • @Job_September_2020 是的,如果实施了适当的比较器(使用显示的任何技术),find() 将起作用。
  • 谢谢。当我按照您的建议编写比较器 operator
  • @Job_September_2020 "我想知道如果我不写比较器 operator== 或 operator!= 而我只需要写 operator,为什么 find() 会起作用- 因为std::map 根本不使用其他运算符,它只根据operator&lt; 执行比较。 “是不是因为编译器足够聪明,以至于从 operator” - 不。编译器与此无关。这严格来说是 std::map 设计工作方式的实现细节
【解决方案2】:

std::tie 允许简单的字典比较:

struct Compare {
    bool operator()(const key& lhs, const key& rhs) const {
        return std::tie(lhs.year, lhs.no) < std::tie(rhs.year, rhs.no);
    }
};

方法/函数as_tuple 可能很有趣,可以避免一些重复:

struct key { int year; int no; };

auto as_tuple(const key& k) { return std::tie(k.year, k.no); }

struct Compare {
    bool operator()(const key& lhs, const key& rhs) const {
        return as_tuple(lhs) < as_tuple(rhs);
    }
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-03
    • 2017-11-14
    • 1970-01-01
    • 1970-01-01
    • 2022-01-11
    • 2015-06-21
    相关资源
    最近更新 更多