在此代码中:
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]
代码是否正确?
答案 0 :(得分:7)
代码错了。 typedef
是现有类型的新名称。因此,您无法创建类型为foo foo;
的类型等于int int
的变量。
g++ -std=c++14
是正确的。
答案 1 :(得分:0)
我会说CLang在这里是正确的 - 即使我从不使用它。
C ++ 14草案N4296在 7.1说明符[dcl.spec] 3
中说如果在解析decl-specifier-seq时遇到类型名称,则将其解释为decl-specifier的一部分 - seq当且仅当在decl-specifier-seq中没有除cv-qualifier之外的先前类型说明符时。该 序列应如下所述自洽。 [例如:
typedef char * Pc;
静态Pc; //错误:名称缺失这里,声明静态Pc格式错误,因为没有为Pc类型的静态变量指定名称。
要获取一个名为Pc的变量,必须存在一个类型说明符(const或volatile除外)以指示 typedef-name Pc是(重新)声明的名称,而不是decl-specifier序列的一部分。
另一个例子,
void f(const Pc); // void f(char * const)(不是const char *)
void g(const int Pc); // void g(const int)
(强调我的)
即使一个例子不是规范性的,也可以认为对于C ++规范的编写者来说,变量可以重新声明typedef的名称。
但是g ++更加保守,看起来更合理。如果我在生产代码中看到这样的构造,程序员很快就会学会不再这样做,即使编译器接受了它......