web-dev-qa-db-ja.com

C ++で「静的列挙」とはどういう意味ですか?

私は最近これに遭遇しました:

static enum Response{
    NO_ERROR=0,
    MISSING_DESCRIPTOR,
    ...
};

コンパイルし、Microsoft VS2005で動作します。ただし、 'static'修飾子が何をするのかわからない。次と違うものはありますか?

enum Response {
    NO_ERROR=0,
    MISSING_DESCRIPTOR,
    ...
};
32
Marcin K

省略記号を削除しただけの正確なコードは、有効なC++ではありません。 static宣言でenumストレージクラス指定子を使用することはできません。そこでは意味がありません(staticとして宣言できるのは、オブジェクト、関数、および匿名ユニオンのみです)。

ただし、enumと変数をすべて1つの宣言で宣言できます。

static enum Response {
    NO_ERROR = 0,
    MISSING_DESCRIPTOR
} x; 

ここのstaticxに適用され、あなたが言った場合と事実上同じです:

enum Response { 
    NO_ERROR = 0,
    MISSING_DESCRIPTOR
};

static Response x;
57
James McNellis

驚くべきことに、他のdecl-specifiersもそこに入れることができます。
VS2008で正常にコンパイルされます。

auto const enum TestEnum {
    Why,
    Does
};

register volatile enum TestEnum2 {
    This,
    Work
};

しかし、それはまったく意味がありません:)

私はここの問題は構文解析にあると思われます、なぜならこのようなコード:

enum TestEnum3 { Hello, World };  // Define enum
enum TestEnum3 x = World;         // Use enum

次のように書くこともできます。

enum TestEnum3 { Hello, World } x = World; // Define and use enum.

興味深いことに、VS2008でこれを行うと気づきます。

enum TestEnum3 { Hello, World };
const enum TestEnum3 e3 = World;
const enum TestEnum4 { F, M, L } e4 = F;

e3 = Hello; // error C2166: l-value specifies const object (Good!)
e4 = M;     // NO ERROR here though - why?

したがって、それらはTestEnum4場合は、constdecl-specifierを捨てているようです。すべて非常に奇妙です。

14
GrahamS
static enum Response { /*... */ };

C++ではstatic enumを定義できません。 staticは、enumのvariableのみであり、type自体ではありません!

GCC version 4.3.4を使用してコードをコンパイルすると、次のエラーが発生します。

prog.cpp:7:エラー:ストレージクラスはオブジェクトと関数にのみ指定できます

Ideoneでオンラインで自分自身を参照してください: http://www.ideone.com/cI1bt

それがすべてだと思います。

-

ただし、typeenum Responseを独自の翻訳単位に制限する場合は、名前のない名前空間を使用できます。このトピックをご覧ください:

静的よりも名前のない名前空間の優位性

7
Nawaz

標準

C++ 11 N3337標準ドラフト Annex C 7.1.1は、Cでは許可されたが、効果はなく、C++では違法になったと述べています。

変更:C++では、静的または外部指定子はオブジェクトまたは関数の名前にのみ適用できます。これらの指定子を型宣言で使用することは、C++では無効です。 Cでは、これらの指定子は型宣言で使用されると無視されます。例:

static struct S {    // valid C, invalid in C++
  int i;
};

根拠:ストレージクラス指定子は、型に関連付けられている場合、意味を持ちません。 C++では、静的ストレージクラス指定子を使用してクラスメンバーを宣言できます。型宣言でストレージクラス指定子を許可すると、コードがユーザーを混乱させる可能性があります。

structと同様に、enumも型宣言です。

実装根拠

Enum定義にはストレージがなく、変数や関数などのオブジェクトファイルにシンボルを生成しません。コンパイルと逆コンパイルを試してください:

struct S { int i; int j; };
int i;

で:

g++ -c main.c
nm main.o

Sシンボルはありませんが、iシンボルはあります。

コンパイラーが列挙値を認識すると、コンパイルされたコードにそのまま挿入されます。コンパイル時の定数であるため、これはもちろん機能します。

したがって、ヘッダーファイルに含める必要があります。

こちらもご覧ください:

C#の場合:

「;」 enumブロックの後の下位互換性のためにオプションです。 notは、名前付き型のその言語でそのようなセマンティクスを許可します。 static、publicなどには特別な考慮事項があります。名前空間にフィールドやメソッドなどのメンバーを含めることはできません。

タグが必要:

ArgTypes var = ArgTypes.CUT;

C/C++の場合:

「;」が必要列挙ブロックの最後。グローバル名前空間変数、列挙などの場合、デフォルトではstaticです。

int type;

typedef enum {
  TOKENIZE,
  CUT
} ArgTypes;
type = TOKENIZE;  /* <ArgTypes>::TOKENIZE */
type = ArgTypes::CUT;

// Recommended Use
enum ArgTypes {
  TOKENIZE,
  CUT
};  /* Same as above */

enum Test {
  TOKENIZE,
  CUT
} ArgTypes;
type = ArgTypes::TOKENIZE;
type = CUT;   /* Assign type =>  <Test>.CUT */
type = Test::CUT;

enum {
  TOKENIZE,
  CUT
} ArgTypes;  /* Unamed.. requires tag */
type = TOKENIZE; /* <unamed>.TOKENIZE=0 => #define TOKENIZE 0*/
type = ArgTypes::TOKENIZE;  /* ** ERROR ** */
1
Latency

なぜstaticが使用されたのか、なぜコンパイルされるのかわからない。単なる列挙型応答である必要があります。列挙子は静的データではありません。

0
JonH