我提出了一个定义一个通用比较运算符的想法,该运算符适用于任何类型,以获得它的乐趣。
#include <cstring>
#include <iostream>
class A
{
public:
A(int id) : id(id) {}
private:
int id;
};
template <class T>
inline bool operator==(const T& a, const T& b)
{
return memcmp(&a, &b, sizeof(a)) == 0; // implementation is unimportant (can fail because of padding)
}
int main()
{
std::cout << (A(10) == A(10)) << std::endl; // 1
std::cout << (A(10) == A(15)) << std::endl; // 0
}
我认为这可以解决c ++中缺少默认比较运算符的问题。
这是一个糟糕的主意吗?我想知道在某些情况下这样做是否会破坏任何事情?
答案 0 :(得分:52)
这样做确实是一个糟糕的主意。
如果某些类型没有定义相等运算符,很可能是因为您无法合理地比较该类型的两个对象是否相等。
即使对于缺少相等运算符是实施者的疏忽的情况,您提出的任何“全能”实施都高度不太可能做出明智的事情。†功能
总结如下:不要这样做!编译时错误优于运行时错误;而不是过早地添加一个隐藏实际问题的最肯定的“解决方案”,在编译时错误发生时添加实际的解决方案。
†对于初学者来说,你提出的解决方案对于带填充的类型,带有重载的一元operator&
的类型以及任何具有某些指针或引用的类型的成员都是失败的;甚至包含任何上述类别的任何成员或基础的类型。所以对于 ton 的东西。
答案 1 :(得分:25)
让我们选择一个完全正常的课程,比如说String
。它是按照您的想法实现的,char*
指向new[]
的缓冲区。\ n \ n}
现在比较其中两个。显然,String("abc")==String("abc")
。然而你的实现未通过此测试,因为两个指针不同。
Equality由类语义定义,而不是由对象内部的位定义。
答案 2 :(得分:5)
是的,这是一个可怕的想法:
如果是未初始化的指针:
这是一个失败的示例(因此此代码有两个不同的输出):
#include <cstring>
#include <iostream>
class A {
public:
A(int id) : id(id) {}
private:
int id;
A* a;
};
template <class T> inline bool operator==(const T &a, const T &b) {
return memcmp(&a, &b, sizeof(a)) == 0;
}
int main() {
std::cout << (A(10) == A(10)) << std::endl; // 1
std::cout << (A(10) == A(15)) << std::endl; // 0
}
输出:
0
0
并且两个指针的两个相同值的RAM初始内容的可能性很小,然后另一个输出是:
1
0
答案 3 :(得分:1)
稍微说,我知道为具有大量成员的类编写相等运算符的最好方法是使用这个想法(此代码需要C ++ 14):
#include <tuple>
struct foo
{
int x = 1;
double y = 42.0;
char z = 'z';
auto
members() const
{
return std::tie(x, y, z);
}
};
inline bool
operator==(const foo& lhs, const foo& rhs)
{
return lhs.members() == rhs.members();
}
int
main()
{
foo f1;
foo f2;
return f1 == f2;
}