【问题标题】:Variable with same name as type - which compiler is right?与类型同名的变量 - 哪个编译器是正确的?
【发布时间】:2016-03-30 17:44:52
【问题描述】:

在这段代码中:

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]

代码正确吗?

【问题讨论】:

  • 我想说 GCC 在这里是正确的
  • 根据诊断状态,您可以使用-fpermissive 开关强制编译...但是为什么要这样做而不是修复代码!?我宁愿得到一个可以悄悄接受的错误,隐藏未来的维护问题。
  • @Clifford,-fpermissiveerror 转换为warning。但问题依然存在。将此语句放在任何类方法中都会导致错误:auto x = foo(5); 而且,我认为 OP 并不是故意在代码中引入这样的命名。大多数情况下,这是一个好奇的问题,即使是我多年前关于这个确切的话题。这就是为什么重新打开这个问题。
  • typedef changes meaning的可能重复
  • Visual Studio 2015 也接受此代码

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


【解决方案1】:

代码错误。 typedef 是现有类型的新名称。所以你不能创建一个类型名称像foo foo;等于int int的变量。

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

Also refer this question

【讨论】:

    【解决方案2】:

    我会说 CLang 在这里是正确的 - 即使我从不使用它。

    C++ 14 草案 N4296 在 7.1 Specifiers [dcl.spec] 3

    中说

    如果在解析 decl-specifier-seq 时遇到类型名称,它会被解释为 decl-specifier- seq 当且仅当 decl-specifier-seq 中除了 cv-qualifier 之外没有先前的类型说明符。这 序列应是自洽的,如下所述。 [ 例子:

    typedef char* Pc;
    静态电脑; // 错误:名称丢失

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

    【讨论】:

    • 从程序读者的角度思考。你可以发现 g++ 是正确的。如您所见,任何变量声明为 foo foo !会烦他们。使用变量 foo 也很困难。这就是为什么对两件事使用一个通用名称并不是最好的,甚至在现实世界中也不只是 C。
    • @LetUsEmbed:我同意你的观点,任何程序员都不应该编写这样的代码!我回答的问题是:该标准对该代码有何规定?
    猜你喜欢
    • 1970-01-01
    • 2018-03-30
    • 2021-06-03
    • 1970-01-01
    • 2021-11-30
    • 1970-01-01
    • 2014-12-31
    • 2017-04-25
    • 2011-11-20
    相关资源
    最近更新 更多