与类型同名的变量 - 哪个编译器是对的?

时间:2015-12-24 09:05:57

标签: c++ compiler-errors clang language-lawyer variable-names

在此代码中:

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]

代码是否正确?

2 个答案:

答案 0 :(得分:7)

代码错了。 typedef是现有类型的新名称。因此,您无法创建类型为foo foo;的类型等于int int的变量。

g++ -std=c++14是正确的。

Also refer this question

答案 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 ++更加保守,看起来更合理。如果我在生产代码中看到这样的构造,程序员很快就会学会不再这样做,即使编译器接受了它......