このコードは、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 以上の異なる組み合わせ) のために、宣言を共用体定義の外に移動することに依存しませんが、他に解決策がない場合は実行されます。