【问题标题】:Can a variable be redeclared as auto that deduced to the same type? [duplicate]可以将变量重新声明为推导出为相同类型的 auto 吗? [复制]
【发布时间】:2016-05-24 07:57:07
【问题描述】:

标准是否允许以下​​内容?

#include <iostream>

extern int a;
auto a = 3;

int main(int, char**)
{
    std::cout << a << std::endl;
    return 0;
}

clang 接受代码。 g++ 抱怨声明冲突。

【问题讨论】:

  • 这肯定是一个 g++ 错误
  • 此代码在 MS Visual Studio 2012 中也会导致错误,提示为 error C2371: 'a' : redefinition; different basic types
  • 怎么样:extern int a; decltype(a) a; ;)
  • @Ajay 应该没问题。偶数:extern int a; decltype(a) a = 42;
  • 它将被 [basic.link]/10 "在所有类型调整后(在此期间 typedefs (7.1.3) 被其定义替换),所有声明指定的类型都引用给定的变量或函数应相同," .似乎很难争辩 autoa 指定了与 int 不同的类型,但即使您确实争辩说,我也很有信心说,目的是让这段代码合法

标签: c++ c++11 language-lawyer extern auto


【解决方案1】:

从标准上我不太清楚,但是,有这样写的

第 7.1.6.4 节自动说明符
在本节未明确允许的上下文中使用 auto 的程序是格式错误的。

最好阅读标准中提到的所有允许上下文的部分。

考虑到这一点,我认为 g++ 是正确的,而 clang 是错误的。但我可能错了,标准中可能有一些单独的部分可能暗示这种情况,但我找不到。

【讨论】:

  • 但是auto a = 3; 这里是明确允许的上下文。 " 在块 (6.3)、在命名空间范围内 (3.3.6)、[...] 中声明变量时,允许使用此用法
  • 也许在上下文意义上(对外)它不适用?或者 g++ 和 clang 对它的解释不同,因为在这种情况下标准语言似乎很松散。
【解决方案2】:

编辑答案: 正如在 cmets 中提到的那样。在这种情况下的问题是写

external int a;
auto a = 3;

和写一样

external int a;
int a = 3;

这意味着你有一个新的 a 定义,这会导致错误。

第一个答案: 据我了解,这破坏了 One 定义规则的部分内容。具体来说,我指的是以下规则(参考 MISRA C++ 2008),即具有外部链接的标识符应始终只有一个定义。在您的示例中,您在当前文件中有一个定义(auto a = 3;),而外部文件中您还引用了另一个文件中的定义。

【讨论】:

  • 在这个例子中,变量只定义了一次。除非auto a 与原始声明冲突,否则不会违反 odr。 Extern 不必引用另一个文件中的定义。它只是引用 some 文件中的定义。可以在声明为 extern 的同一文件中定义变量。
  • Jamboree 在问题中展示了程序的完整代码。其中只有一个a 的定义。当然,如果您通过将此 TU 与其他 TU 关联来添加更多定义,那么您可能会违反 ODR,但我认为这不是问题所在,因为这与 auto 无关。
  • @cpow extern int a; 是声明,int a = 3; 是定义
  • 换一种说法,如果包含extern名称定义的文件不允许包含其他所有人都包含的相同头文件,包含extern宣言。幸运的是,他们被允许这样做,这就是你在这里看到的全部。这是包含 a 的(一个)定义的 TU,它还有一个 extern 声明。
  • ODR 无论如何都无关紧要,我们谈论的是在同一单位内重新声明。相关规则是[basic.link]/10
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-03
  • 2016-09-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多