遮蔽外部名称的 decltype 和类成员名称之间的交互

2021-12-18 00:00:00 gcc scope language-lawyer c++ decltype

此代码

int clash;

struct Foo {
  decltype(clash) clash;
};

在 clang 上静默编译,但在 gcc 上编译失败并出现错误

compiles silently on clang, but fails to compile on gcc giving the errors

错误:'int Foo::clash'的声明[-fpermissive]

error: declaration of 'int Foo::clash' [-fpermissive]

错误:将 'clash' 的含义从 'int crash' [-fpermissive] 更改为

error: changes meaning of 'clash' from 'int clash' [-fpermissive]

似乎需要 2 个因素才能出现错误:

It seems that 2 ingredients are required for the error to arise:

  1. 阴影必须由类成员完成(如果是函数的局部作用域,没问题).

  1. The shadowing must be done by a class member (no problem if it's a function's local scope).

decltype([shadowed name]) 必须在声明[shadowing name]之前的shadowing作用域中使用.

decltype([shadowed name]) must be used in the shadowing scope before the declaration of [shadowing name].

我的问题是双重的:

  1. gcc 拒绝此代码是否合理?
  2. 标准中哪里这么说的?

推荐答案

gcc 是正确的程序格式错误,尽管这种特殊的违规不需要诊断所以 clang代码>不必提供.

gcc is correct the program is ill-formed, although this particular violation does not require a diagnostic so clang does not have to provide one.

如果我们看一下 C++11 标准(最接近的草案是 N3337) 部分 3.3.7 Class scope 它说:

If we look at the C++11 standard(The closest draft would be N3337) section 3.3.7 Class scope it says:

在类 S 中使用的名称 N 应在其上下文以及在 S 的完整范围内重新评估时.否违反此规则需要进行诊断.

A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S. No diagnostic is required for a violation of this rule.

然后下一条规则说:

如果重新排序类中的成员声明会产生一个替代的有效(1) 和 (2) 下的程序,程序格式错误,没有诊断需要.

If reordering member declarations in a class yields an alternate valid program under (1) and (2), the program is ill-formed, no diagnostic is required.

我们希望防止重新排序类中的声明给出不同程序的情况是有道理的.很好奇这两条规则是否多余.

It makes sense we would want to prevent situations where reordering the declarations in a class give a different program. It is curious whether these two rules are redundant or not.

该部分还提供了以下示例:

The section also provides the following example:

enum { i = 1 };

class X {
  char v[i]; // error: i refers to ::i
             // but when reevaluated is X::i
  int f() { return sizeof(c); } // OK: X::c
  char c;
  enum { i = 2 };
};

如果我们用 gcc (现场观看),我们得到的错误与您的代码产生的错误几乎相同:

and if we try this example with gcc (see it live), we get an almost identical error to one your code produces:

 error: declaration of 'i' [-fpermissive]
 enum { i = 2 };
          ^

 error: changes meaning of 'i' from '<anonymous enum> i' [-fpermissive]
 enum { i = 1 };

相关文章