C ++列挙は、コンパイラによって適切に認識されていません
-
22-08-2019 - |
質問
次のコードがコンパイルされない理由を誰でも説明できますか(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
}
これはより読みやすく、基本的に同じ効果があります。