C++ 具有自定义比较函子的集合,在相等的情况下可预测
我正在尝试构建一个带有自定义顺序的C++ 具有自定义比较函子的集合,在相等的情况下可预测,c++,set,comparison,key,C++,Set,Comparison,Key,我正在尝试构建一个带有自定义顺序的std::set,以在其中存储“任务”,我想知道是否有可能通过一个普通的std容器获得我需要的东西 这个场景是这样的: std::set<Task*, CompareTasks> taskList; 但是,我随后插入的任务,已经记录了优先级,只是。。根本没有插入。因此,我怀疑taskList的键是优先级本身,而不是std::set中写入的指针值Task*。我怎样才能确认这是否属实 更引人注目的是:由于在为std容器创建比较函数时,排序必须是弱的,因
std::set
,以在其中存储“任务”,我想知道是否有可能通过一个普通的std
容器获得我需要的东西
这个场景是这样的:
std::set<Task*, CompareTasks> taskList;
但是,我随后插入的任务,已经记录了优先级
,只是。。根本没有插入。因此,我怀疑taskList
的键是优先级本身,而不是std::set
中写入的指针值Task*
。我怎样才能确认这是否属实
更引人注目的是:由于在为
std
容器创建比较函数时,排序必须是弱的,因此有没有任何方法可以仅通过std::set
实现这一点?当您提供比较器时,std::set
的等价定义是!公司(a、b)和&!comp(b,a)
。使用比较函数,您将无法插入两个具有相同优先级的Task*
s,因为根据该定义,它们是等效的
您需要的是std::multiset
——特别是C++11std::multiset
,因为其insert()
中未包含此保证(;这是本标准表102§23.2.4[关联.reqmts]要求的):
如果容器包含具有等效键的元素,则在该范围的上限处插入
这意味着新插入的元素将始终位于容器中已存在的等效元素之后
请注意,标准有序关联容器按非降序排序,因此如果希望任务按优先级降低排序,则需要更改函子。提供比较器时,
std::set
的等价性定义是!公司(a、b)和&!comp(b,a)
。使用比较函数,您将无法插入两个具有相同优先级的Task*
s,因为根据该定义,它们是等效的
您需要的是std::multiset
——特别是C++11std::multiset
,因为其insert()
中未包含此保证(;这是本标准表102§23.2.4[关联.reqmts]要求的):
如果容器包含具有等效键的元素,则在该范围的上限处插入
这意味着新插入的元素将始终位于容器中已存在的等效元素之后
请注意,标准有序关联容器按非降序排序,因此如果希望任务按优先级递减排序,则需要更改functor。好的,这是C++11的一个很好的保证,我将尝试使用multiset。谢谢我现在想知道这个
std::set
:它们应该是指向任务的指针,而不是优先级,对吗?然后,具有相同优先级的两个不同的任务
应具有两个不同的任务*
地址,因此不被视为“已复制”。。这个推理有什么问题?好吧,我想它越来越清楚了:它们确实有不同的键,但它们被认为是“等价的”,因为我提供了这个比较器。。棘手的技巧:POkay,它现在在多集上确实可以工作,但我觉得我在战斗中失去了一些东西:现在如何确保相同的任务*
不会在std::multiset任务列表中插入两次?我必须自己处理吗?这就是使用一个简单的std::set
的初衷\@Iago lito如果您使用multiset
,那么您必须自己跟踪重复的指针(可以很容易地维护std::set
,旁边没有自定义比较器)。使用set
的问题在于,您需要让比较器以某种方式知道插入时间,这是很棘手的。非常正确。事实上,我意识到使用multiset
跟踪重复指针一点也不困难(我只需要在类任务中添加一个bool sent
成员,每次检查该成员,如果任务已发送到列表中,则返回true
,删除后返回false
)。所以它终于起作用了。。完美地再次感谢T.C.:)好的,很好,这是来自C++11的一个很好的保证,我将尝试使用多集。谢谢我现在想知道这个std::set
:它们应该是指向任务的指针,而不是优先级,对吗?然后,具有相同优先级的两个不同的任务
应具有两个不同的任务*
地址,因此不被视为“已复制”。。这个推理有什么问题?好吧,我想它越来越清楚了:它们确实有不同的键,但它们被认为是“等价的”,因为我提供了这个比较器。。棘手的技巧:POkay,它现在在多集上确实可以工作,但我觉得我在战斗中失去了一些东西:现在如何确保相同的任务*
不会在std::multiset任务列表中插入两次?我必须自己处理吗?这就是使用一个简单的std::set
的初衷\@Iago lito如果您使用multiset
,那么您必须自己跟踪重复的指针(可以很容易地维护std::set
,旁边没有自定义比较器)。使用set
的问题在于,您需要让比较器以某种方式知道插入时间,这是很棘手的。非常正确。事实上,我意识到使用multiset
跟踪重复指针一点也不困难(我只需要在类任务中添加一个bool sent
成员,每次检查该成员,如果任务已发送到列表中,fa,则该成员将变为true
class CompareTasks
{
public:
bool operator()(Task* const& a, Task* const& b)
{
return a->priority < b->priority;
}
};