VS2012 不编译此代码,但 G++、clang 和 ICC 都在没有诊断的情况下接受它

VS2012 doesn't compile this code, but G++, clang, and ICC all accept it without a diagnostic

基于this answer, I came up with 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) : error C2065: 'n' : undeclared identifier

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

将其简化为一个简单的

unsigned char x(x);

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

这是一个编译器错误。引用标准(N4140,大致为C++14,但规则与早期标准相同):

3.3.2 Point of declaration [basic.scope.pdecl]

1 The point of declaration for a name is immediately after its complete declarator (Clause 8) and before its initializer (if any), except as noted below. [Example:

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

Here the second x is initialized with its own (indeterminate) value. -- end example ]

= x;(x); 在语法上都是 初始化器 ,在 (x); 语法中没有任何例外,变量 x 不知何故还不在范围内。

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

但由于它只影响在自身初始化中使用变量的代码,因此更好的 re-working 代码可以完全避免该问题。