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++11
std::multiset
,因为其
insert()
中未包含此保证(;这是本标准表102§23.2.4[关联.reqmts]要求的):

如果容器包含具有等效键的元素,则在该范围的上限处插入

这意味着新插入的元素将始终位于容器中已存在的等效元素之后


请注意,标准有序关联容器按非降序排序,因此如果希望任务按优先级降低排序,则需要更改函子。

提供比较器时,
std::set
的等价性定义是
!公司(a、b)和&!comp(b,a)
。使用比较函数,您将无法插入两个具有相同优先级的
Task*
s,因为根据该定义,它们是等效的

您需要的是
std::multiset
——特别是C++11
std::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;
    }
};