GLM + STL:运算符 == 缺失

Posted

技术标签:

【中文标题】GLM + STL:运算符 == 缺失【英文标题】:GLM + STL: operator == missing 【发布时间】:2010-08-17 09:44:20 【问题描述】:

我尝试在 STL 容器中使用 GLM 矢量类。只要我不尝试使用<algorithm>,没什么大不了的。大多数算法都依赖于 == 运算符,而 GLM 类并未实现该运算符。

有人知道解决此问题的简单方法吗?无需(重新)实现 STL 算法:(

GLM 是一个很棒的数学库,在 c++ 中实现了 GLSL 函数

更新

我刚刚发现 glm 实际上在扩展中实现了比较运算符 (here)。但是我如何在 stl 中使用它们呢?

更新 2

这个问题已经被这个问题取代了:how to use glm's operator== in stl algorithms?

【问题讨论】:

我不确定哪个答案更像是一个黑客...... 它们都不是黑客。它们都是非常好的和惯用的解决方案。请记住,运算符有效地扩展了类型:如果您定义 operator==,所有客户端都会假定它是 测试相等性的方法。如果它用于 STL 算法,那么仿函数可能是更好的选择。这对于相等可能没问题(尽管您有时可能想要使用变量 epsilon),但对于operator< 来说这可能是个坏主意,因为没有明显的方法来定义一个向量是否“小于”另一个,所以当那个需要,我会使用仿函数。 【参考方案1】:

许多 STL 算法接受函子进行对象比较(当然,在比较两个包含浮点值的向量是否相等时,您需要特别小心)。

例子:

要对std::list<glm::vec3> 进行排序(由您决定以这种方式对向量进行排序是否具有实际意义),您可以使用

std::sort(myVec3List.begin(), myVec3List.end(), MyVec3ComparisonFunc)

bool MyVec3ComparisonFunc(const glm::vec3 &vecA, const glm::vec3 &vecB)

 return vecA[0]<vecB[0] 
        && vecA[1]<vecB[1] 
        && vecA[2]<vecB[2];

所以,谢天谢地,没有必要修改 GLM 甚至重新发明***。

【讨论】:

这是“不错的面向对象”解决方案……我其实很喜欢……但另一个更简单 @Florian:我不确定这个是否更面向对象,但它更灵活。我的使用标准是这是否总是向量的排序方式。如果这是测试一个 glm 向量是否“小于”另一个的唯一方法,请继续定义 operator&lt;(可能不是。例如,向量也可以按长度排序)。否则,将其编写为仿函数,并在需要此特定定义时使用它。 是的......我认为这两个都是有效的答案(如果可能的话,我会将它们都标记为已接受)......但我会这样做glm's的人会有他们不包含 == 运算符的原因,所以我不会自己实现它。谢谢大家!【参考方案2】:

您应该能够将 operator== 实现为独立函数:

// (Actually more Greg S's code than mine.....)

bool operator==(const glm::vec3 &vecA, const glm::vec3 &vecB) 
 
   const double epsilion = 0.0001;  // choose something apprpriate.

   return    fabs(vecA[0] -vecB[0]) < epsilion   
          && fabs(vecA[1] -vecB[1]) < epsilion   
          && fabs(vecA[2] -vecB[2]) < epsilion;
 

【讨论】:

再看看我/你的代码,我的比较函数类似于operator&lt;,而不是operator== ;-),所以你可能需要按照return fabs(vecA[0]-vecB[0]) &lt; epsilon &amp;&amp; ... 的方式重写它. 这是更简单的解决方案……我其实很喜欢……但另一个更面向对象:/ @Florian :不,这两种解决方案具有相同的“OOP 深度”。 James 的解决方案是全局的,决定了使用 operator == 函数比较 GLM 向量的“正常”方式。 Greg S 的解决方案更具上下文特定性:对于 this 或 this 处理或容器,应使用 this 或 this 函子进行比较...结论:如果您认为只有一种(或只有一种主要)方法可以比较 GLM 向量,然后将实现放在operator == 函数中。【参考方案3】:

James Curran 和 Greg S 已经向您展示了解决问题的两种主要方法。

定义要在需要它的 STL 算法中显式使用的函子,或 定义实际运算符==&lt;,如果未指定函子,STL 算法将使用这些运算符。

这两种解决方案都非常好且惯用,但在定义运算符时要记住的一点是它们有效地扩展了类型。一旦你为glm::vec3 定义了operator&lt;,这些向量被扩展以定义“小于”关系,这意味着任何时候有人想要测试一个向量是否“小于”另一个,他们将使用您的运营商。因此,只有在普遍适用的情况下才应使用运算符。如果这是始终定义 3D 向量之间小于关系的唯一且唯一的方法,请继续将其设为运算符。

问题是,它可能不是。我们可以用几种不同的方式对向量进行排序,但显然没有一个是“正确的”。例如,您可以按长度对向量进行排序。或者根据x 组件的大小,忽略yz 。或者您可以使用所有三个组件定义某种关系(例如,如果 a.x == b.x,检查 y 坐标。如果它们相等,检查 z 坐标)

没有明显的方法来定义一个向量是否“小于”另一个向量,因此运算符可能是一种不好的方法。

对于相等,运算符可能会更好。我们确实有一个向量相等的定义:如果每个分量相等,则两个向量相等。

这里唯一的问题是向量由浮点值组成,因此您可能需要进行某种 epsilon 比较,以便在所有成员几乎相等的情况下它们是相等的。但是您可能还希望 epsilon 是可变的,而这不能在 operator== 中完成,因为它只需要两个参数。

当然,operator== 可以只使用某种默认的 epsilon 值,并且可以定义函子用于与变量 epsilon 进行比较。

没有明确的答案可以选择。这两种技术都是有效的。只需选择最适合您的需求。

【讨论】:

以上是关于GLM + STL:运算符 == 缺失的主要内容,如果未能解决你的问题,请参考以下文章

STL重载运算符

实际stl中默认赋值运算符是如何实现的

使用 STL utility.h 重载运算符

C ++ STL - 相当于具有赋值的运算符函数对象模板?

STL 结构体内重载 一个比较运算符

STL详解—— list的模拟实现