【问题标题】:C++ Map<>.find() overloading for different class不同类的 C++ Map<>.find() 重载
【发布时间】:2013-07-19 16:07:37
【问题描述】:

我尝试使用定义为的地图:

    map<Vertex,unsigned int> _addedVertices; 

现在当我使用 find 函数检查顶点是否已经在里面时 我用不同的信息得到了一个指向错误顶点的迭代器,所以我尝试了以下方法:

    map<Vertex,unsigned int,cmpByVertexFields> _addedVertices; 

这没有帮助。

我在 Vertex 类中有以下重载函数。

    bool operator<(const Vertex &otherV)const{
        return(_x<otherV._x && _y<otherV._y && _z<otherV._z);
    }
    bool operator==(const Vertex &otherV)const{
        return _x==otherV._x && _y==otherV._y && _z==otherV._z;
    }

但没有任何效果。 例子: 我插入了一个包含 (0.2,0.1,0.4) 的顶点 接下来我使用的是带有 (0.2,0.15,0.41) 的查找功能 我得到的迭代器是第一个顶点而不是 map.end()。

我忘了定义什么? 谢谢

编辑:cmpByVertexFields:

struct cmpByVertexFields {
    bool operator()(const Vertex& a, const Vertex& b) const {
        return a.getX()==b.getX() &&
            a.getY()==b.getY() &&
            a.getZ()==b.getZ();
    }
};

【问题讨论】:

  • 您的小于 operator&lt; 没有实现 strict weak ordering。这是std::map 正常运行的要求。
  • 我第一次只使用了 x
  • 顺便说一句,您根本不需要 operator == 来使用地图的查找
  • 我建议您阅读有关字典顺序的内容。基本上一个有 N 个字段的结构有点像一个有 N 个字符的字符串,现在用你的运算符比较“ab”和“ba”:"ab" &lt; "ba"&lt;=&gt;'a' &lt; 'b' and 'b' &lt; 'a'true and false@987654332 @,但我们知道“ab”小于“ba”:)

标签: c++ map operator-overloading


【解决方案1】:

正如 Juan 在评论中所说,您的 operator &lt; 实现在语义上是不正确的。由于您在谈论顶点,因此您实际上需要在 _x_y_z 之间实现字典比较。

最简单的方法是使用std::tuple built-in comparison:

bool operator<(const Vertex &otherV)const{
    return std::tie(_x, _y, _z) < std::tie(otherV._x, otherV._y, otherV._z);
}

Using std::tie in this way 现在是跨(成员)变量的the established way of implementing a lexicographical comparison(您实际上可以将其用于operator== 实现)。

【讨论】:

  • 感谢大家,我花了一段时间才明白这个错误,但现在我明白了为什么它不是一个好的比较功能。干杯
【解决方案2】:

这是你的罪魁祸首

bool operator<(const Vertex &otherV)const{
        return(_x<otherV._x && _y<otherV._y && _z<otherV._z);
    }

这不会产生strict weak ordering

你需要这样的东西

bool operator<(const Vertex &otherV)const{
        if(_x != otherV.x)
               return _x < otherV.x;
        if(_y != otherV.y)
               return _y < otherV.y;
        return _z < otherV.z;
    }

或者,等效且更方便地,使用 std::tie 将它们作为元组进行比较

bool operator<(const Vertex &otherV)const{
       return std::tie(x_, y_, z_) < std::tie(OtherV.x_, OtherV.y_, OtherV.z_);
}

【讨论】:

    【解决方案3】:

    比较函子或小于operator&lt; 必须实现strict weak ordering。这是std::map 的要求。你的没有。没有明显和自然的方式来排序 3D 顶点,但是如果您想按字典顺序按 xyz 坐标排序,那么最简单的方法是使用 std::tie(或 boost::tiestd::tr1::tie 如果你没有 C++11 支持):

    bool operator<(const Vertex &otherV)const{
        return std::tie(_x, _y, _z) < std::tie(otherV._x, otherV._y, otherV._z);
    }
    

    请注意,这种排序完全是任意的:为什么x 优先于y?实施适合您要解决的问题的排序取决于您。另一方面,如果您不关心地图元素的实际排序,则任何严格的弱排序都可以。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多