集合的重载运算符

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&lt; 用于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 运算符重载 ( 运算符重载 | 运算符重载对应方法 )

运算符重载1

C++ 运算符重载

什么运算符一定要重载友元函数,什么时候一定要重载为成员函数?

利用运算符重载实现Date类