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

у следующий код не компилируется под 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
 besc01 дек. 2017 г., 18:41
@Ivan Itявляется стандарт. Квалифицированные перечислители разрешены даже для перечислений старого стиля; см. стандарт C ++ 11 [dcl.enum] (10).
 DaBler01 дек. 2017 г., 18:21
использованиеError{value_1};
 underscore_d01 дек. 2017 г., 16:46
Без того, чтобы вы оба не указали, с каким компилятором он работал / не работал, отчет не интересен. Это может быть расширение, но я еще не проанализировал грамматику.
 Pete Becker01 дек. 2017 г., 16:38
Отредактированный заголовок: нетбросать в этом коде; вопрос опреобразование.

Ответы на вопрос(3)

Решение Вопроса

что и «Самый мексиканский синтаксический анализ» - правило, что если оно может быть объявлением, оноявляется декларация
И, что удивительно, вам разрешено заключать скобки вокруг идентификатора в объявлении переменной.
(Я понятия не имею, почему, но я предполагаю, что это упростило синтаксический анализатор Си в те времена.)

Ниже приведены все действительные декларацииint переменные:

int (foo);
int (bar) = 0;
int (baz)(3);
int (twaddle)(baz);
 StaceyGirl01 дек. 2017 г., 16:51
Почему скобки разрешены, объясняется в K & R.
 Bo Persson01 дек. 2017 г., 23:42
В некоторых объявлениях, как указатель на функциюint* (*f)();вам нужны круглые скобки, чтобы звездочки ассоциировались с правильным именем. Так что им разрешено. Там просто нет правил, говорящих, когда вы должныне используйте их, чтобы они могли быть добавлены в любое время.
 DevSolar01 дек. 2017 г., 17:02
 JAB01 дек. 2017 г., 19:11
@Ivan Есть ли у вас ссылка / цитата для конкретной части K & R, о которой идет речь?
 StaceyGirl01 дек. 2017 г., 19:14
@JAB Нет, но это та часть, которая объясняет, как работают определения типов. Упоминается в моем ответе.

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

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] указатель на массив из 8intх (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.

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

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

Error(value_1);

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

Error  value_1;

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

Ваш ответ на вопрос