質問

次のコードがコンパイルされない理由を誰でも説明できますか(G ++(GCC)3.2.3 20030502(Red Hat Linux 3.2.3-49))?

struct X {
public:
   enum State { A, B, C };

   X(State s) {}
};

int main()
{
   X(X::A);
}

私が得るメッセージは次のとおりです。

jjj.cpp:infunction 'int main()':
jjj.cpp:10: 'xx :: a'は 'struct x'の静的メンバーではありません
jjj.cpp:10:「x :: x()」への呼び出しの一致関数なし
jjj.cpp:1:候補者はx :: x(const x&)です
jjj.cpp:5:x :: x(x :: state) `

これは悪いコードですか、それともコンパイラのバグですか?

ニール+コンラッドによって解決された問題。以下のニールの回答へのコメントを参照してください。

役に立ちましたか?

解決

X(X::A);

ASA機能宣言が見られています。本当にこのコードが必要な場合は、以下を使用してください。

(X)(X::A);

他のヒント

定義の変数名を忘れてしまいました。

int main()
{
   X my_x(X::A);
}

構文的にこれを関数宣言と区別できないため、コードはコンパイラを混乱させます(返信 X そして通過 X::A 議論として)。疑わしい場合、C ++コンパイラは常に宣言を支持して曖昧になります。

解決策は、周囲に冗長な括弧を導入することです X コンパイラはタイプの周りの括弧を禁止するため(Constructo Callsなどとは対照的に):

(X(X::A));

何が起こるかを明確にするためだけに。この例を見てください

int main() {
    float a = 0;
    {
        int(a); // no-op?
        a = 1;
    }
    cout << a;
}

何が出力されますか?まあ、それは出力されます 0. 。 int(a) 上記の2つの異なる方法で解析できます。

  • INTにキャストし、結果を破棄します
  • 呼ばれる変数を宣言します a. 。ただし、識別子の周りの括弧は無視します。

コンパイラは、声明で機能スタイルのキャストが使用され、宣言のように見えるような状況が表示される場合、常に宣言としてそれを受け取ります。構文的に宣言ではない場合(コンパイラはそれを決定するために行全体を調べます)、それは表現と見なされます。したがって、内側に割り当てています a 上、外側を残します a ゼロで。

さて、あなたのケースはまさにそれです。 (誤って)識別子を宣言しようとしています A 呼ばれるクラス内 X:

X (X::A); // parsed as X X::A;

その後、コンパイラは、宣言されていないデフォルトコンストラクターについてうめきます。これは、静的がデフォルト構築されているためです。しかし、Xのデフォルトコンストラクターがあったとしても、もちろんどちらも間違っています。 A xの静的メンバーであり、xの静的はブロックスコープで定義/宣言することもできます。

うまくいくよ いいえ いくつかのことをすることで宣言のように見えます。まず、表現全体をパレンすることができます。これにより、宣言のように見えなくなります。または、キャストされるタイプのパレンだけです。これらの曖昧性は両方とも、他の回答で言及されています。

(X(X::A)); (X)(X::A)

オブジェクトを実際に宣言しようとすると、同様の、しかし明確なあいまいさがあります。この例を見てください:

int main() {
    float a = 0;
    int b(int(a)); // object or function?
}

なぜなら int(a) 呼び出されたパラメーターの宣言の両方にすることができます a そして、intへのフロート可変の明示的な変換(キャスト)であるコンパイラは、それが宣言であると再び決定します。したがって、たまたま呼ばれる関数を宣言します b, 、整数の引数を取り、整数を返します。上記の曖昧性に基づいて、それを想定する方法はいくつかあります。

int b((int(a))); int b((int)a);

オブジェクトを次のように宣言する必要があります

X x(X::A);

コードのバグ。

これらの2つの行のいずれかが私のために機能します:

X obj(X::A);
X obj2 = X(X::A);

ニール・バターワースが指摘しているように、 X(X::A) 関数宣言として扱われています。本当に匿名のオブジェクトが必要な場合は、 (X)(X::A) Xオブジェクトを構築し、すぐに削除します。

もちろん、あなたはただこのようなことをすることができます:

int main()
{
    // code
    {
    X temp(X::A);
    }
    // more code
}

これはより読みやすく、基本的に同じ効果があります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top