C ++ Enum не распознается должным образом компилятором

StackOverflow https://stackoverflow.com/questions/681518

Вопрос

Может ли кто-нибудь объяснить, почему следующий код не компилируется (на G ++ (GCC) 3.2.3 2003050202 (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: в функции '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 Поскольку компилятор запрещает скобки вокруг типов (в отличие от конструктивных вызовов и т. Д.):

(X(X::A));

Просто чтобы прояснить, что происходит. Посмотрите на этот пример

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

Что он выведет? Ну, это выведет 0. Анкет А int(a) из вышеупомянутого может быть проанализировано двумя разными способами:

  • Бросить в 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);

Ошибка в вашем коде.

Любая из этих двух строк работает для меня:

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