C++ std::映射不使用自定义对象删除重复项

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);

全部

<>所以,我创建了一个可比较的基类(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); }
  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应被视为相等

有人知道发生了什么事吗

编辑:关于为什么代码是这样设计的,有很多问题

我需要满足两个条件:

  • 具有相同ID的对象必须被视为“相同”对象,而不考虑其值
  • 不具有相同ID的对象必须根据其值进行排序(该值是什么,取决于对象的类型)
  • 这是因为创建这些对象的数据来自未经验证的源。如果该源提供的数据具有相同的ID但值不同,则该数据无效

    编辑2:关于std::map的严格弱排序。假设有两个Foo对象,A和B

    如果它们的ID相等,则A 这不应该满足严格的订购规则吗

    在任何情况下,如果std::set使用小于运算符(默认情况下是这样),它是否应该按设计工作


    编辑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;
    }