【问题标题】:std::map key no match for operator< [duplicate]std::map 键不匹配运算符< [重复]
【发布时间】:2014-07-15 19:40:24
【问题描述】:

我很难调试我的一小段代码:

std::map<glm::ivec3,int> myMap;
glm::ivec3 myVec(3, 3, 3);
myMap.find(myVec);

我收到以下错误:

c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\bits\stl_function.h|237|error: no match for 'operator&lt;' in '__x &lt; __y'

这是否意味着我无法检查 glm::ivec3 是否小于另一个?
我认为因为订购了stl::map,所以编译器想要检查哪一对先出现。我试图使键成为指针并且它起作用了。

有没有办法让键保持值而不是指针?这让我问另一个问题:如何将无法比较或比较慢的东西与大于操作进行比较?

谢谢! :)

【问题讨论】:

  • 真的有bool oprerator&lt;(const glm::ivec3&amp;,const glm::ivec3&amp;)availabla吗??
  • 不,如果我不想更改源,我不知道是否可以添加一个(我不是 C++ 专业人士)。
  • 检查建议的重复和答案,这些应该有助于解决您的问题(无需更改旧源)。
  • 我不同意这是引用链接的副本。在这种情况下没有自然排序,所以 map 并不是一个很好的选择。

标签: c++ dictionary stl std glm-math


【解决方案1】:

我不熟悉glm,但从数学上讲,这并不让我感到惊讶,因为向量没有自然顺序; IE。当两者可以在 3d 空间中的任何位置时,u unordered_map(哈希表),除非您的问题需要排序.

这是一个讨论 Java hashCode() 函数的链接,其中讨论了复合对象散列的各种方法。

http://www.javamex.com/tutorials/collections/hash_function_guidelines.shtml

对于一个状态为三个整数的类,我可能会做(((x*p)+y)*p)+z 其中p 是一个小素数,比如31。(这有很多变化,更复杂的函数取决于数据结构等)

这里有更多来自 SO 的关于 C++ 散列的链接。

unordered_map hash function c++

C++ unordered_map using a custom class type as the key

【讨论】:

  • 你知道 unordered_map 和自定义键(自制类)的好教程吗?我不知道如何制作哈希函数。我找到的每个教程都向我展示了如何将 unordered_map 与 int 或字符串一起使用...
【解决方案2】:

你可以实现一个比较函数:

bool operator<(const glm::ivec& lhs, const glm::ivec& rhs)
{
    return lhs.x < rhs.x ||
           lhs.x == rhs.x && (lhs.y < rhs.y || lhs.y == rhs.y && lhs.z < rhs.z);
}

(根据需要将.x.y.z 更改为[0][1][2] / .first().second().third() 等。

如何将无法比较或比较慢的东西与大于操作进行比较?

您的指针破解并不少见,但并不总是有用,必须小心操作 - 特别是,如果有人在地图中搜索并想要找到现有元素,他们需要指向相同元素的指针先前存储在地图中的现有对象。或者,选择一些任意顺序,即使它在现实世界中没有特别的意义——只要它是一致的。

如果比较速度很慢,您可能会先比较哈希值,然后再使用较慢的比较来处理罕见的冲突(或者如果您的哈希足够长/足够强,return false 假设他们'相等)。

【讨论】:

  • +1:或者,return std::tie(lhs.x,lhs.y,lhs.z) &lt; std::tie(rhs.x,rhs.y,rhs.z);,如果您想节省击键并拥有兼容的 C++11 实现。
  • 我不知道具体是什么,但我的直觉告诉我……闻到这个解决方案的味道。看看lhs,rhs 是地形向量表示,比较操作可能只是表示向量的真实'长度'
  • @πάνταῥεῖ 我同意。您需要某种 严格的弱排序才能使用std::map,但3D 向量没有“自然”排序,因此它可能应该是一个比较函子,而不是operator &lt;。跨度>
猜你喜欢
  • 2016-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-10
  • 1970-01-01
  • 2014-07-13
  • 1970-01-01
  • 2018-07-19
相关资源
最近更新 更多