集合的重载运算符
Posted
技术标签:
【中文标题】集合的重载运算符【英文标题】:Overloading operator for set 【发布时间】:2014-11-20 02:36:40 【问题描述】:我正在使用 std::set 来实现特定的算法。该集合中有重复项,所以我认为我必须重载运算符。重载看起来像这样。
class Vec3f
...
bool operator () ( const Vector3f& v0, const Vector3f& v1 ) const
float epsilon = 1e-7;
return ((v1[0] - v0[0]) > epsilon) && ((v1[1] - v0[1]) > epsilon) && ((v1[2] - v0[2]) > epsilon);
...
"Vec3f.h"
int main()
...
std::set<Vec3f,Vec3f> visited;
...
我重载了它,所以我可以使用 std::set 中所需的
【问题讨论】:
【参考方案1】:正如您现在所拥有的,v0
中的每个组件都必须小于 v1
中的每个组件。这不是严格的弱排序。您应该一次检查一个组件。仅当您当前检查的组件相等时才检查后续组件。此外,您应该删除 epsilon。虽然这对于检查浮点计算结果的等价性很有用,但对于排序没有用,因为它也违反了严格的弱排序。最简单的方法是将operator<
用于std::tuple
return std::tie(v0[0], v0[1], v0[2]) < std::tie(v1[0], v1[1], v1[2]);
否则,如果你想手动实现它,它是这样的:
if (v0[0] < v1[0]) return true;
if (v0[0] > v1[0]) return false;
if (v0[1] < v1[1]) return true;
if (v0[1] > v1[1]) return false;
if (v0[2] < v1[2]) return true;
if (v0[2] > v1[2]) return false;
return false;
【讨论】:
很好地使用std::tie
来测试字典顺序,尽管我很确定在这种情况下设计本身存在缺陷,不应该尝试订购 3D 向量
@vsoftco:有时能够以某种方式订购东西很有用,即使订购标准是完全任意的。仅出于搜索目的。【参考方案2】:
用std::abs
比较和epsilon
的区别,点赞
if(std::abs(v1[0]-v0[1]) > epsilon && ...)... // not zero
否则您可能会得到负面结果
它总是小于你的epsilon
,并且规范测试会失败。
PS:一般来说,尝试对向量进行排序是一个坏主意,因为没有直观的数学排序,您可能会遇到很多奇怪和违反直觉的情况。
【讨论】:
我尝试这样做,但违反严格弱并导致运行时错误。 @TringVu 啊,好吧,我明白了,你不能按规范对向量进行排序,就像你不能对复数引入一个maninful ordering。你应该考虑一下不同的排序。你可以例如首先比较绝对值,然后是角度,但同样,在数学上它并没有太大意义。【参考方案3】:您提到您只是想使用一个集合,而不一定是需要排序的集合的实现。您可能会考虑使用std::unordered_set
,它不需要您定义排序,只需定义哈希/相等函数。
【讨论】:
以上是关于集合的重载运算符的主要内容,如果未能解决你的问题,请参考以下文章
Groovy集合遍历 ( 操作符重载 | 集合中的 “ + “ 操作符重载 | 集合中的 “ - “ 操作符重载 | 代码示例 )
GroovyGroovy 运算符重载 ( 运算符重载 | 运算符重载对应方法 )