1

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

4

3 に答える 3

2

名前のないstructs は標準で許可されていないため (それらは一般的な拡張機能ですが)、どちらが正しいかを言うのは困難です。したがって、プログラムは不正な形式です。

編集: 完全に有効な次のコードがコンパイルに失敗するため、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不要なandを削除したことに注意してくださいinline

于 2009-07-12T07:28:27.237 に答える