Подтвердить что ты не робот

С++: что означает "static enum"

Я недавно наткнулся на это:

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

Он компилируется и работает под MSVS2005. Однако я не уверен, что должен делать "статический" модификатор. Разве это не отличается от следующего?

enum Response {
    NO_ERROR=0,
    MISSING_DESCRIPTOR,
    ...
};
4b9b3361

Ответ 1

Этот точный код с удаленным многоточием недействителен С++. Вы не можете использовать спецификатор класса static в объявлении enum; это не имеет никакого смысла (только объекты, функции и анонимные объединения могут быть объявлены static).

Вы можете, однако, объявить enum и переменную все в одном объявлении:

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

static здесь относится к x, и это фактически так же, как если бы вы сказали:

enum Response { 
    NO_ERROR = 0,
    MISSING_DESCRIPTOR
};

static Response x;

Ответ 2

Удивительно, что вы также можете добавить туда других спецификаторов decl. Это компилируется в 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, это, похоже, выбрасывает спецификатор объявления const. Все очень странно.

Ответ 3

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

Вы не можете определить static enum в С++. static может быть только переменной перечисления, а не самого типа!

Компиляция вашего кода с помощью GCC version 4.3.4, он дает эту ошибку:

prog.cpp: 7: ошибка: класс хранения может только для объектов и Функции

Посмотрите себя онлайн на ideone: http://www.ideone.com/cI1bt

Я думаю, что все это говорит.

-

Однако, если вы хотите ограничить тип enum Response в своей собственной единицы перевода, вы можете использовать неназванное пространство имен. Взгляните на эту тему:

Превосходство неназванного пространства имен по статическому?

Ответ 4

Стандартный

С++ 11 N3337 стандартный проект. Приложение C 7.1.1 говорит, что оно разрешено на C, но не имело эффекта и стало незаконно в С++:

Изменить: в С++ статические или внешние спецификации могут применяться только к именам объектов или функций. Использование этих спецификаторов с объявлениями типов является незаконным в С++. В C эти спецификаторы игнорируются при использовании на объявления типов. Пример:

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

Обоснование: Спецификаторы класса хранения не имеют никакого значения при привязке к типу. В С++ класс члены могут быть объявлены с помощью спецификатора класса статического хранилища. Разрешение спецификаторов класса хранения по типу объявления могут сделать код запутанным для пользователей.

И как struct, enum также является объявлением типа.

Обоснование реализации

Определения Enum не имеют хранилища и не создают символов в объектных файлах, таких как переменные и функции. Просто попробуйте выполнить компиляцию и декомпиляцию:

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

с:

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

и вы увидите, что символ S отсутствует, но есть символ i.

Когда компилятор видит значения перечисления, он просто вставляет его буквально в скомпилированный код. Это только работает, конечно, потому что они являются константами времени компиляции.

Поэтому они должны быть включены в файлы заголовков.

См. также:

Ответ 5

В С#:

";" является необязательным для обратной совместимости после блока перечисления. Он не допускает такую ​​семантику на этом языке для именованных типов. статические, общественные и т.д. Пространство имен не может содержать элементы, такие как поля или методы.

Требуется тег:

ArgTypes var = ArgTypes.CUT;

В C/С++:

Требуется ';' в конце блока перечисления. Для глобальных переменных пространства имен, перечислений и т.д. Статический по умолчанию.

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 ** */

Ответ 6

Я не уверен, почему статичность была использована или почему она даже компилируется. Должно просто быть перечисление ответа. Перечислители не являются статическими данными.