В каких ситуациях следует использовать анонимное перечисление?

В обоих случаях c и С++ enum могут быть определены с тегом

enum e_smth {
    smth_one,
    smth_two,
    smth_err
};

или без тега

enum {
    smth_one,
    smth_two,
    smth_err
};

Если он был определен с помощью тега, он имеет смысл в операторах switch как в c, так и в С++:

e_smth some_var;
....//do some stuff with some_var
switch (some_var)
{
case smth_one:
break;
case smth_two:
break;
}

будет выдавать предупреждение -Wswitch, если оно будет скомпилировано с помощью gcc или g++.

Это имеет смысл в инициализации объявлений и инициализации переменных в С++:

e_smth var;
var=99;

Произведет ошибку -fpermissive, если скомпилирован с g++.

Оба типа с тегом или без него могут использоваться как один макрос файла #define без параметров.


Обновление

может использоваться как один файл #define макрос без параметров

означало: вместо записи #define MAX 1000 в файл и добавления MAX к глобальному использованию enum { MAX=1000 } только в области содержимого


А как насчет анонимных перечислений, я нашел только один случай использования: определение типа typedef enum { a,b,c } some_t; заставляет его работать как enum с тегом

Вопрос:

если я еще не описал все разумные варианты использования, что использовать анонимные перечисления?

Ответ 1

В C (но не в С++) enum может быть [ab] использоваться для определения констант int.

Например, с учетом этого объявления:

const int MAX = 1024;

MAX не является постоянным выражением, это имя объекта только для чтения. Это означает, что вы не можете использовать его в ярлыке case, как размер массива, объявленного в области содержимого или с помощью static, или в любом другом контексте, требующем постоянного выражения.

Но если вы пишете:

enum { MAX = 1024 };

тогда MAX является константным выражением типа int, которое можно использовать в любом контексте, где вы могли бы использовать константу 1024.

Конечно, вы также можете написать:

#define MAX 1024

но есть недостатки в использовании препроцессора: идентификатор не охвачен тем, как ему было бы присвоено обычное объявление, например.

Недостатком является то, что такая константа может быть только типа int.

С++ имеет разные правила; константы перечисления имеют нумерованный тип, а не int, но вы можете использовать объявленные постоянные объекты как константные выражения (пока инициализатор является постоянным выражением).

Чтобы решить исходный вопрос, когда вы используете объявление enum для создания таких констант, нет смысла иметь либо тег, либо typedef, поскольку вы никогда не будете использовать сам тип.

Фон: Это:

enum foo { zero, one, two };
enum foo obj = two;

создает тип enum foo и константы zero, one и two. В C константы всегда имеют тип int, что, по общему признанию, нечетное, а инициализация obj подразумевает неявное преобразование от int до enum foo.

В С++ тип enum foo также можно назвать просто foo, а константы имеют тип enum foo (который совместим с целым типом, не обязательно int).

Ответ 2

Другой вариант использования - это элемент struct или union, как правило, когда нет смысла использовать его сам по себе (потому что он должен исключительно удовлетворять ABI протокола связи или т.д. и т.д. существует более подходящее представление для программного использования).

Ответ 3

@eth Thompson

В вашем ответе есть утверждение, что "const int MAX = 1024; MAX не является постоянным выражением ". Однако пример из ссылки http://en.cppreference.com/w/cpp/language/constant_expression показывает, что это константное выражение и может использоваться в объявлении массива. Константные выражения Выражения языка С++ С++ Определяет выражение, которое может быть оценено во время компиляции.

Такие выражения могут использоваться как аргументы шаблона непигового типа, размеры массива и в других контекстах, которые требуют постоянных выражений, например

int n = 1;
std::array<int, n> a1; // error, n is not a constant expression
const int cn = 2;
std::array<int, cn> a2; // OK, cn is a constant expression

Ответ 4

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

enum color { red, blue, gray, green };
enum color car_color;
enum color house_color;

Здесь есть несколько переменных, поэтому enum назван.

typedef struct {
    int year;
    enum { Jan, Feb, Mar, Apr, May, Jun, July, Aug, Sep, Oct, Nov, Dec } month;
    unsigned int day;
} date;

Здесь автор планирует использовать enum только один раз, поэтому имя не нужно.