C++ std::映射不使用自定义对象删除重复项
全部 <>所以,我创建了一个可比较的基类(LA java),它完成C++中的比较运算符重载。这是:C++ std::映射不使用自定义对象删除重复项,c++,map,comparator,standard-library,C++,Map,Comparator,Standard Library,全部 所以,我创建了一个可比较的基类(LA java),它完成C++中的比较运算符重载。这是: template <class T> class Comparable { public: bool operator== (const T& rhs) const { return this->compare(rhs) == 0; } bool operator!= (const T& rhs) const { return !(*this == rhs);
template <class T>
class Comparable {
public:
bool operator== (const T& rhs) const { return this->compare(rhs) == 0; }
bool operator!= (const T& rhs) const { return !(*this == rhs); }
bool operator< (const T& rhs) const { return this->compare(rhs) < 0; }
bool operator<= (const T& rhs) const { return (*this == rhs) || (*this < rhs); }
bool operator> (const T& rhs) const { return this->compare(rhs) > 0; }
bool operator>= (const T& rhs) const { return (*this == rhs) || (*this > rhs); }
protected:
virtual int compare (const T& rhs) const = 0;
};
到目前为止,我认为还不错
但是,当我尝试在std::set容器中存储Foo对象时,该集合将不会消除重复项。也就是说,其中仍然会有包含相同ID的对象,即使该ID应被视为相等
有人知道发生了什么事吗
编辑:关于为什么代码是这样设计的,有很多问题
我需要满足两个条件:
编辑3:
std::set
,而不是std::map
。我真是太蠢了。抱歉。std::map
不会通过操作符==
确定重复项。它使用操作符如果你没有严格的弱排序,你就不能使用映射
,如果你这样做了,你也不能抱怨它不起作用。这是map
的先决条件
编辑:
您的compare
没有实现您指定的语义-如果在第二次测试中\u value==rhs.\u value
,则应返回0
但是有了这个修正,你仍然没有一个一致的顺序——参见Benjamin Lindley在评论中给出的例子。基本上,您的排序没有意义-您需要修复语义,或者停止使用需要一致排序的标准库组件。您的基类缺少虚拟析构函数。如果(\u id==rhs.\u id)返回0;这看起来很奇怪——这意味着不管值是多少,它都是相等的,但如果值是相等的,则稍后处理ID比较。这是哪一个?你对=invoke的定义比较了两次,这似乎是个坏主意。你需要更好的测试map
要求<是严格的弱序;如果不是,你会得到未定义的行为。请参阅,例如,您的比较方法是否实现了严格的弱排序?它将按ID排序,并且仅在ID相同时按值排序。这与我被要求做的恰恰相反。@KarlGiesing:这只是一个例子。关键是,您必须找到一种方法来定义对象的严格弱顺序。如果您无法做到这一点,那么就不能使用std::map
。传递性需求正是问题所在。刚刚证实了。谢谢,这还不够。考虑三个对象,<代码> a <代码> >代码> b <代码> > <代码> c>代码>。代码>自动识别码!=B.id
,但是A.value
,所以A
。现在,C.id==B.id
(因此C.id!=A.id
),但是C.value
。所以C
,和A
。因此,C
应该是
。但事实并非如此,因为C.id==B.id
@Benjamin谢谢。我在努力想出一个反例。我会更新的。@BenjaminLindley:这对我来说是有意义的,我现在明白了。回答这个问题,你就会得到我的选票。@KarlGiesing:我会把它加到我的答案中。
int Foo::compare(const Foo& rhs) const
{
if (_id == rhs._id)
return 0;
// _value is integer data; comparison should sort on this
if (_value == rhs._value)
{
// OK, same data, now sort on ID's
return _id.compare(rhs._id);
}
// Sort on value
return _value - rhs._value;
}
int Foo::compare(const Foo& rhs) const
{
if (_id < rhs._id)
return -1;
if (rhs._id < _id)
return 1;
return _value - rhs._value;
}