c++ - enum си




Почему этот enum не конвертируется в int? (2)

Почему следующий код не компилируется под g ++ (C ++ 14), MSVC (C ++ 14) или ARM (C ++ 03)?

Именованный экземпляр Error вызывает целочисленный конструктор, но анонимный экземпляр Error не разрешается.

class Error
{
public:
    Error(int err) : code_(err) {}
    const int code_;
};

enum Value
{
    value_1
};

int main()
{
    // compiles
    Error e(value_1);

    // does not compile under G++, ARM, or MSVC
    Error(value_1);
}

Пример ошибки в G ++: ( ссылка на Coliru )

g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out

main.cpp: In function 'int main()':
main.cpp:19:18: error: no matching function for call to 'Error::Error()'
     Error(value_1);
                  ^
main.cpp:4:5: note: candidate: Error::Error(int)
     Error(int err) : code_(err) {}
     ^~~~~
main.cpp:4:5: note:   candidate expects 1 argument, 0 provided
main.cpp:1:7: note: candidate: constexpr Error::Error(const Error&)
 class Error
       ^~~~~
main.cpp:1:7: note:   candidate expects 1 argument, 0 provided
main.cpp:1:7: note: candidate: constexpr Error::Error(Error&&)
main.cpp:1:7: note:   candidate expects 1 argument, 0 provided

main.cpp: 19: 18: ошибка: не найдена соответствующая функция для вызова Error :: Error ()
Ошибка (значение_1);

Компилятор пытается вызвать несуществующий конструктор по умолчанию Error::Error() потому что видит

Error(value_1);

как объявление переменной

Error  value_1;

Декларация может иметь избыточные круглые скобки.


Проблема в том, что код

Error(value_1);

является объявлением переменной value_1 типа Error .

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

Например, int *i - указатель на int потому что он говорит, что выражение *i должно вычисляться для типа int . Еще примеры этого:

  • int (*func)() - указатель на функцию, возвращающую int потому что выражение (*func)() тип int .
  • int *p[8] - это массив указателей на int потому что выражение *p[x] оценивается как тип int .
  • int (*p)[8] является указателем на массив из 8 int '( int[8] ), потому что выражение (*p)[x] оценивается как тип int .
  • int (*(*p[8])())() - это массив из 8 указателей на функции, возвращающие указатели на функцию, возвращающую int потому что выражение (*(*p[x])())() тип int ,

Точно так же int (i) является простой переменной типа int поскольку выражение (i) вычисляется как тип int .

И так как C ++ наследует это от C, он использует круглые скобки как часть объявления типа, но также добавляет сверху синтаксис, что приводит к неожиданным результатам.

Правило, применяемое здесь C ++, говорит, что все, что может быть объявлением, рассматривается как объявление.

Подобная путаница, если часто вызывается кодом вроде этого

Error ec();

которая является предварительным объявлением функции ec которая возвращает Error .





enums