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<
(可能不是。例如,向量也可以按长度排序)。否则,将其编写为仿函数,并在需要此特定定义时使用它。
是的......我认为这两个都是有效的答案(如果可能的话,我会将它们都标记为已接受)......但我会这样做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<
,而不是operator==
;-),所以你可能需要按照return fabs(vecA[0]-vecB[0]) < epsilon && ...
的方式重写它.
这是更简单的解决方案……我其实很喜欢……但另一个更面向对象:/
@Florian :不,这两种解决方案具有相同的“OOP 深度”。 James 的解决方案是全局的,决定了使用 operator ==
函数比较 GLM 向量的“正常”方式。 Greg S 的解决方案更具上下文特定性:对于 this 或 this 处理或容器,应使用 this 或 this 函子进行比较...结论:如果您认为只有一种(或只有一种主要)方法可以比较 GLM 向量,然后将实现放在operator ==
函数中。【参考方案3】:
James Curran 和 Greg S 已经向您展示了解决问题的两种主要方法。
定义要在需要它的 STL 算法中显式使用的函子,或 定义实际运算符==
和<
,如果未指定函子,STL 算法将使用这些运算符。
这两种解决方案都非常好且惯用,但在定义运算符时要记住的一点是它们有效地扩展了类型。一旦你为glm::vec3
定义了operator<
,这些向量被扩展以定义“小于”关系,这意味着任何时候有人想要测试一个向量是否“小于”另一个,他们将使用您的运营商。因此,只有在普遍适用的情况下才应使用运算符。如果这是始终定义 3D 向量之间小于关系的唯一且唯一的方法,请继续将其设为运算符。
问题是,它可能不是。我们可以用几种不同的方式对向量进行排序,但显然没有一个是“正确的”。例如,您可以按长度对向量进行排序。或者根据x
组件的大小,忽略y
和z
。或者您可以使用所有三个组件定义某种关系(例如,如果 a.x == b.x,检查 y 坐标。如果它们相等,检查 z 坐标)
没有明显的方法来定义一个向量是否“小于”另一个向量,因此运算符可能是一种不好的方法。
对于相等,运算符可能会更好。我们确实有一个向量相等的定义:如果每个分量相等,则两个向量相等。
这里唯一的问题是向量由浮点值组成,因此您可能需要进行某种 epsilon 比较,以便在所有成员几乎相等的情况下它们是相等的。但是您可能还希望 epsilon 是可变的,而这不能在 operator==
中完成,因为它只需要两个参数。
当然,operator==
可以只使用某种默认的 epsilon 值,并且可以定义函子用于与变量 epsilon 进行比较。
没有明确的答案可以选择。这两种技术都是有效的。只需选择最适合您的需求。
【讨论】:
以上是关于GLM + STL:运算符 == 缺失的主要内容,如果未能解决你的问题,请参考以下文章