这段代码在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
哪个编译器是正确的?怎么解决这个问题?我正在尝试实现干净的代码(没有外部朋友方法),同时保持可移植性,灵活性和自我记录代码。
有些说明:
最优解决方案不会依赖于因为aestetic原因(超过24种不同的运算符和操作数组合)而在联合定义之外移动声明,但如果没有其他解决方案,则会完成。
答案 0 :(得分:2)
很难说哪一个是正确的,因为标准不允许未命名的struct
(尽管它们是一个共同的扩展名),因此该程序是不正确的。
编辑:这似乎是msvc中的一个错误,因为以下代码完全无效,无法编译。
union buggedUnion
{
friend buggedUnion operator - (int A, const buggedUnion &B) {
return B;
}
friend buggedUnion operator - (const buggedUnion &A, const buggedUnion &B) {
return A;
}
int i;
};
int main()
{
buggedUnion first = { 1 };
buggedUnion second = { 1 };
buggedUnion result = 3 - (first - second);
}
您可以通过定义类外的函数来解决此问题。
union buggedUnion
{
int i;
};
buggedUnion operator - (int A, const buggedUnion &B) {
return B;
}
buggedUnion operator - (const buggedUnion &A, const buggedUnion &B) {
return A;
}
你甚至可以通过声明类中的函数来保留朋友状态(但仍在外部定义它们),但我怀疑你是否需要在联盟中使用它。
请注意,我删除了不必要的typedef
和inline
。
答案 1 :(得分:0)
您需要在封闭范围内声明这些友元函数,因为一旦在类中声明它们,它们就不再在外部范围中可见。因此,要么像avakar所说的那样将函数体移出类,要么将它们保留在类中并添加以下行以将名称重新引入封闭范围:
extern const buggedUnion operator-(const buggedUnion& A, const buggedUnion&B);
int main()
{
...etc
希望这会有所帮助。不确定它是否是一个错误,但它似乎(?)对我来说是正确的行为,现在正确实现,许多编译器用来解释不同。请参阅:http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Dialect-Options.html中的--ffriend-injection。
答案 2 :(得分:0)
以下代码在Visual C ++ 2008中正确编译:
union buggedUnion
{
int i;
friend buggedUnion operator - (int A, const buggedUnion &B);
friend buggedUnion operator - (const buggedUnion &A, const buggedUnion &B);
};
buggedUnion operator - (int A, const buggedUnion &B)
{
return B;
}
buggedUnion operator - (const buggedUnion &A, const buggedUnion &B)
{
return A;
}
虽然MSDN文档声明在类中编写友元函数的定义实际上将函数放在文件范围内,但这似乎对联合不起作用。因为它适用于类和结构,我怀疑这可能是一个错误。由于我上面给出的实现应该适用于GCC,我认为它可以被认为是一种合适的解决方法,并且该错误可能无法在MSVC中修复。