这段代码在 GCC 3.x 和 4.x 上按预期编译和运行:
#include <stdio.h>
typedef union buggedUnion
{
public:
// 4 var init constructor
inline buggedUnion(int _i) {
i = _i;
}
friend inline const buggedUnion operator - (int A, const buggedUnion &B) {
return buggedUnion(A - B.i);
}
friend inline const buggedUnion operator - (const buggedUnion &A, const buggedUnion &B) {
return buggedUnion(A.i - B.i);
}
int i;
} buggedUnion;
int main()
{
buggedUnion first(10);
buggedUnion second(5);
buggedUnion result = 10 - (first - second);
printf("%d\n", result.i); // 0
return 0;
}
但是,MSVC 不会编译该代码,并抱怨:
main.cpp(60) : error C3767: '-': candidate function(s) not accessible
could be the friend function at 'main.cpp(41)' : '-' [may be found via argument-dependent lookup]
or the friend function at 'main.cpp(45)' : '-' [may be found via argument-dependent lookup]
main.cpp(60) : error C2676: binary '-' : 'buggedUnion' does not define this operator or a conversion to a type acceptable to the predefined operator
哪个编译器是正确的?如何解决?我试图在保持可移植性、灵活性和自记录代码的同时实现干净的代码(没有外部朋友方法)。
一些注意事项:
- 这是一个显示问题的测试用例,原始数据类型更加复杂和精心设计,尽管在 MSVC 中不起作用(主编译器是 GCC,但也需要 MSVC 兼容性)。
- 在联合声明的开头添加 'public:' 并不能解决它。
- 在每个运营商不解决它之前添加 'public:'
- 将测试用例转换为结构/类确实可以解决它,但这是不希望的(请不要发火,我有理由。其中大多数是 C++ 语言的限制)
- 运算符方法将保留在全局范围内(不是成员函数)
出于美学原因(超过 24 种不同的运算符和操作数组合),最佳解决方案不会依赖于将声明移到联合定义之外,但如果没有其他解决方案,则会这样做。