排序集没有严格的弱排序

时间:2015-11-03 18:37:17

标签: c++ c++11 containers strict-weak-ordering

我有以下问题:考虑这个(简化的)结构:

struct Task {
    int priority;
    std::string description;
    // Some other fields
};

现在我希望拥有一系列所有任务并使用它完成一些工作。因此,我有一个相等运算符,它检查每个元素是否相等。

bool isEqual(const Task& lhs, const Task& rhs) {
    return lhs.priority == rhs.priority &&
        lhs.description == rhs.description &&
        // Some other fields
        ;
}

为此,我使用了std :: unordered_set,它工作正常。

但是现在我希望这些任务按照它们的优先级(以获得最高优先级的任务)进行排序。显然这对于​​std :: unordered_set是不可能的,所以我尝试使用以下less运算符的std :: set:

bool lessTask(const Task& lhs, const Task& rhs) {
    return lhs.priority < rhs.priority;
}

但这意味着严格的弱顺序,两个任务是相等的,当优先级相等时,我不想要(我想维护我的isEqual方法进行相等性检查)。

完成一组任务的最佳方法是什么,我可以非常快速地插入元素并且没有重复的条目(由我的isEqual函数定义),但是能够真正快速地检索具有最高优先级的任务吗? /> 我不受任何特定STL容器的约束,但不想使用任何第三方库(甚至不是boost)。

2 个答案:

答案 0 :(得分:1)

当您将元素放入地图时,通常需要将该类的所有成员添加到less。否则它将无法正常工作。当我不得不创建一个包含在地图中的大约15个不断变化的classess的系统时,这是一个巨大的挑战,而这正是我真正开始错过编译时的反思。

在旁注中,您可以使用优先级队列std::make_heap)代替地图。优先级堆不关心相等性,并且首先会为您提供具有最高优先级的任务。

答案 1 :(得分:1)

首先写get_tie

// auto or decltype(auto)
auto get_tie(const Task& task) {
  return std::tie(lhs.priority, lhs.description, /* some other fields */ );
}

在C ++ 11中,您必须使用->decltype尾随返回类型重复主体,或使用宏来避免重复:

#define RETURNS(...) decltype(__VA_ARGS__) { return __VA_ARGS__; }
auto get_tie(const Task& task)->
RETURNS( std::tie(lhs.priority, lhs.description, /* some other fields */ ) )

一旦我们轻松get_tie,您的问题就会消失。

bool isEqual( Task const& lhs, Task const& rhs ) {
  return get_tie(lhs)==get_tie(rhs);
}
bool isLess( Task const& lhs, Task const& rhs ) {
  return get_tie(lhs) < get_tie(rhs);
}

只需将isLess传递给std::set,或使用std::vector构建std::sortisLess

现在,如果您的比较并非真正适用于原始tie引用,则可能必须将get_tie替换为更复杂的内容。