【问题标题】:VS2012 doesn't compile this code, but G++, clang, and ICC all accept it without a diagnosticVS2012 不编译此代码,但 G++、clang 和 ICC 都接受它而无需诊断
【发布时间】:2017-02-08 17:23:10
【问题描述】:

基于this answer,我想出了this code 用于C++ 中的常量树结构:

#include <tuple>
struct T
{
    T(const char* n, const T& n1, const T& n2, const T& n3, const T& n4):
        name(n), nodes(n1, n2, n3, n4) {}

    const char* name;
    std::tuple<const T&, const T&, const T&, const T&> nodes;
};

T n(0, n, n, n, n);

GCC(4.5.3 和最新版本)、ICC (17) 和 CLang(3.5 和最新版本)都编译此代码(CLang 3.5 对其发出 -Wuninitialized 警告,但这没关系,因为 n是一个占位符,其值无关紧要)。

然而,MSVC 11 (VS2012) 对 n 的定义产生了 C2065 错误:

test6.cpp(12) : 错误 C2065: 'n' : 未声明的标识符

什么给了? MSVC 是否拒绝有效代码?我是不是在 UB 的土地上,恶魔从我的鼻子里飞出来?如果这无效,有人可以告诉我标准中的什么使它无效和/或为什么 GCC、Clang 和 ICC 都接受它?

【问题讨论】:

  • 即使这是有效的 C++,这也不是一个好主意...
  • std::tuple 在 c++11 标准中可用。 VS2012 不支持。
  • @SamVarshavchik -- 如果不依赖于我们的占位符 n 的值,为什么让它未初始化会不好?还是您要指出其他问题? (我宁愿做一些更好的事情,但我的工具包中没有太多 C++11 意味着我很受限制......)
  • 这个测试用例可以缩短为int i(i);。这是 VC++ 不接受的部分。您的 struct T 和您的元组与此问题无关。
  • @πάνταῥεῖ -- ...什么新语法?

标签: c++ visual-studio-2012


【解决方案1】:

简化为一个简单的

unsigned char x(x);

http://webcompiler.cloudapp.net/ 上在线测试表明,当前版本的微软编译器仍然拒绝它。

这是一个编译器错误。引用标准(N4140,大致是C++14,但在早期的标准中规则是一样的):

3.3.2 声明点 [basic.scope.pdecl]

1 名称的声明点紧接在其完整声明符(第 8 条)之后和其初始值设定项(如果有)之前,除非如下所述。 [例子:

unsigned char x = 12;
{ unsigned char x = x; }

这里第二个x 用它自己的(不确定的)值初始化。 -- 结束示例 ]

= x;(x); 在语法上都是一个初始化器,在(x); 语法中,变量x 不会出现在任何地方都不例外范围。

Visual Studio 的编译器使用 = x; 语法接受它。

但由于它只影响在其自身初始化中使用变量的代码,因此更好地重新编写代码将完全避免该问题。

【讨论】:

  • 嗯,struct x; int x(x); 函数还是变量?
  • 这显然是一件很疯狂的事情:第二个x 用它自己的(不确定的)值初始化。所以这是标准中的一个错误,编译器正确地纠正了它。
  • @T.C.与最令人头疼的解析相同:如果它可以是一个函数,它就是一个函数。但我不理解 [dcl.ambig.res] 的措辞:“解决方案是考虑任何可能是声明的构造声明”我不明白这如何涵盖紧随其后的示例,或者你给了,其中函数声明优于变量声明。
  • @Ben -- 既然你坚持认为这是标准中的一个错误 -- 那么你将如何创建 self-referential data type intended for compile-time initialization?
  • @ChristianHackl C++ 没有陷阱表示,那是 C 的东西。在 C++ 中,未初始化的对象具有不确定的值,读取不确定的值具有未定义的行为,即使对于不能具有 C 所谓的陷阱表示的类型也是如此。 unsigned char 有一个特殊的例外情况,但即便如此,它也仅适用于少数有限的情况(包括此答案中的情况)。参见 [dcl.init]p12。
猜你喜欢
  • 2017-06-05
  • 2020-06-03
  • 1970-01-01
  • 2012-12-22
  • 1970-01-01
  • 1970-01-01
  • 2017-01-11
  • 1970-01-01
  • 2023-03-25
相关资源
最近更新 更多