三个主要的编译器(gcc、clang、MSVC)很乐意编译下面的例子(godbolt):
struct Test
{
// Member type `Test::Test` is supposedly introduced at this point
// as an alias to `struct Test`, per https://eel.is/c++draft/class.pre#2
// Shouldn't the following declaration be rejected since it redefines
// the name `Test` in the same scope?
int Test;
// Doing the same explicitly would be a compilation error, as expected:
// using Probe = int;
// int Probe;
};
int main()
{
Test x;
x.Test = 4;
}
**上面的例子是格式良好的吗?**为什么injected-class-name不使成员int Test;
的声明无效?
查找规则[class.member.lookup]/6可能会使这个例子的格式不正确,并且没有诊断,这看起来是不相关的,因为在这个类完成之前,不会进行查找。还有哪些子句与这个例子相关?
1条答案
按热度按时间8zzbczxx1#
根据C++17标准(12.2类成员)
18如果T是一个类的名称,那么下列每一个都应该有一个不同于T的名称:
(18.1)-类T的每个静态数据成员;
(18.2)-类T的每个成员函数[注:这个限制不适用于构造函数,它没有名字(15. 1)--结束注解] ;
(18.3)--类T中本身是一个类型的每一个成员;
(18.4)-T类的每个成员模板;
(18.5)-类T的每个成员的每个枚举数,它是一个无作用域的枚举类型;以及
(18.6)--每个匿名并集的每个成员都是类T的成员。
以及
19此外,如果类T有一个用户声明的构造函数(15.1),类T的每个非静态数据成员都应该有一个不同于T的名字。
因此,由于类没有用户声明的构造函数,因此其非静态数据成员
Test
可能与类名同名。你甚至可以写
(It它似乎是允许与C兼容的,其中结构标记名称和数据成员的名称属于不同的名称空间。)
另一方面,如果将构造函数声明为例如
则编译器将发出错误。
一般来说,C++不允许在同一作用域中声明一个变量和一个函数。