Ответ 1
Насколько я могу судить, это распространяется на черновик стандарта С++ 8.3
Значение абзаца абзаца 6, в котором говорится (акцент мой вперед):
В объявлении T D, где D имеет вид
(D1)
тип содержащегося идентификатора-декларатора совпадает с типом содержащегося идентификатора declarator-id в декларация
T D1
Круглые скобки не изменяют тип встроенного идентификатора declarator-id, но они могут изменять привязку сложного declarators.
так:
int(::x);
эквивалентно:
int ::x ;
что явно недействительно, и это также приводит к той же ошибке. Так что gcc 4.9
здесь неверно, но поскольку это выглядит исправленным в gcc 4.8.3
, который был выпущен позже, я ожидал бы, что это будет исправлено и в последующих выпусках 4.9
. Хотя я не вижу никаких очевидных совпадений для этой проблемы в gcc 4.8.3 ошибках фиксированного списка, но они не утверждают, что это полный список.
Второй случай представляет собой преобразование функционального явного типа, которое рассматривается в разделе 5.2.3
Явное преобразование типа (функциональная нотация), в котором говорится:
Спецификатор простого типа (7.1.6.2) или typename-specifier (14.6) за которым следует заключенный в скобки список выражений, строит значение заданный тип с учетом списка выражений. Если список выражений является одно выражение, выражение преобразования типов эквивалентно (в определенность и определенность в значении) соответствующему литу выражение (5.4). [...]
Это однозначно, так как ::x + 2
является выражением.
Раздел, который охватывает, когда утверждение считается объявлением или выражением, является 6.8
Разрешение неоднозначности, в котором говорится:
Существует двусмысленность в грамматике, включающая выражения-выражения и объявления: выражение expression с функциональным стилем явное преобразование типа (5.2.3), поскольку его самое левое подвыражение может быть неотличимы от декларации, где начинается первый декларатор с. () В этих случаях утверждение является объявлением. [Примечание: для устранить неоднозначность, все выражение, возможно, придется изучить определить, является ли это выражением-выражением или декларацией. Эта неоднозначно много примеров.
и предоставляет следующие примеры:
T(a)->m = 7; // expression-statement T(a)++; // expression-statement T(a,5)<<c; // expression-statement T(*d)(int); // declaration T(e)[5]; // declaration T(f) = { 1, 2 }; // declaration T(*g)(double(3)); // declaration
Примечание: без ()
, тогда T ::D
является квалифицированным id в случае T
, являющимся классом, который рассматривается в грамматике 5.1
Первичных выражений.
Обновить
Подано сообщение gcc bug.
gcc ответ таков:
Текущий g++ и EDG рассматривают его как действительное выражение (int):: x
Поскольку этот ответ подразумевает, что clang
неверен (я не согласен, хотя), я подал отчет об ошибке clang и более старый отчет об ошибках выглядит аналогичным и, похоже, не согласен с ответом gcc
.
Обновление 2
В ответ на clang bug report
Ричард Смит соглашается, что это следует рассматривать как декларацию и говорит:
Это не означает, что clang неверен; на самом деле, Кланг верен здесь, насколько я вижу. (Я также отправил отчет об ошибке в EDG.)
Тем не менее, мы должны дать правильный "вы нажмете на досадный синтаксический разбор, вот как чтобы устранить ошибку в этом случае.
Обновление 3
gcc
подтверждает, это ошибка.