Подтвердить что ты не робот

Переменная с тем же именем, что и тип - какой компилятор прав?

В этом коде:

typedef int foo;

struct S
{
  foo foo;
};

int main() {}

все версии clang -std=c++14 принимают этот код, однако все версии g++ -std=c++14 сообщают:

5 : error: declaration of 'foo S::foo' [-fpermissive]
foo foo;
^
1 : error: changes meaning of 'foo' from 'typedef int foo' [-fpermissive]

Правилен ли код?

4b9b3361

Ответ 1

Код неправильный. typedef - новое имя для существующего типа. Таким образом, вы не можете создать переменную с типом имени типа foo foo;, равным int int.

g++ -std=c++14 является правильным.

Также укажите этот вопрос

Ответ 2

Я бы сказал, что CLang здесь прав, даже если бы я использовал никогда.

С++ 14 черновик N4296 говорит в 7.1 Спецификаторы [dcl.spec] 3

Если во время разбора дескриптора-указателя-seq встречается имя типа, оно интерпретируется как часть описания decl-specifier- seq тогда и только тогда, когда в спецификаторе-спецификаторе-seq нет предыдущего спецификатора типа, отличного от cv-квалификатора. последовательность должна быть самосогласованной, как описано ниже. [Пример:

typedef char * Pc;  Статический ПК; //error: имя отсутствует

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

Чтобы получить переменную с именем Pc, должен присутствовать спецификатор типа (кроме const или volatile), чтобы указать, что typedef-name Pc - это имя, которое (re) объявлено, а не является частью последовательности decl-specifier.

В другом примере

void f (const Pc);//void f (char * const) (не const char *)   
   void g (const int Pc);//void g (const int)

(подчеркните мое)

Даже если пример не является нормативным, пусть он считает, что для писателей спецификации С++ переменная может обновлять имя typedef.

Но g++ просто более консервативен, что выглядит более разумным. Если я когда-либо увижу такую ​​конструкцию в производственном коде, программист скоро научится не делать этого снова, даже я его компилятор принял...