В этом коде:
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]
Код правильный?
Код неверный. typedef
это новое имя для существующего типа. Таким образом, вы не можете создать переменную с именем типа, как foo foo;
равно int int
,
g++ -std=c++14
правильный.
Я бы сказал, что CLang является правильным здесь, даже если бы я никогда использовать этот.
C ++ 14 проект N4296 говорит в 7.1 Спецификаторы [dcl.spec] 3
Если при анализе decl-specier-seq встречается имя типа, оно интерпретируется как часть decl-specier-
seq тогда и только тогда, когда в decl-specier-seq нет предыдущего спецификатора типа, кроме cv-qualifier.
последовательность должна быть самосогласованной, как описано ниже. [ Пример:typedef char * Pc;
статический ПК; // ошибка: имя отсутствуетЗдесь объявление static Pc является неправильно сформированным, поскольку для статической переменной типа Pc не было указано имя.
Чтобы получить переменную с именем Pc, должен присутствовать спецификатор типа (отличный от const или volatile), чтобы указать, что
typedef-name Pc — это объявленное (пере) имя, а не часть последовательности спецификатора decl.Для другого примера
пустота f (const Pc); // void f (char * const) (не const char *)
void g (const int Pc); // void g (const int)
(подчеркните мой)
Даже если пример не является нормативным, он позволяет думать, что для авторов спецификации C ++ переменная может переопределить имя typedef.
Но g ++ просто более консервативен, что выглядит более разумный. Если я когда-либо увижу такую конструкцию в производственном коде, программист вскоре научится не делать это снова, даже если компилятор принял это …