为什么decltype(class :: class :: class :: member)有效

0xF*_*xFF 8 c++ decltype c++11

我意外地注意到这段代码编译并正常工作:

struct M { int some_int; };
static_assert(std::is_same<
                   decltype(M::M::M::M::some_int) /* <- this */,
                   int>::value, "Types must be int");
Run Code Online (Sandbox Code Playgroud)

为什么这是正确的(decltype(M::M::M::M::some_int) <=> decltype(M::some_int))?

还有哪些其他构造可以使用这种模式class::class::...::member

编译器:用于x86的Microsoft(R)C/C++优化编译器版本19.00.23824.1

Rei*_*ica 10

这在所有情况下都有效,而不仅仅是decltype.类包含自己的名称作为注入的类名.因此,在类中A::B::M,M注入名称以引用类A::B::M.这意味着您可以使用它M::M::M::some_member来引用该类的成员,如果您真的想要.

[实例]

请注意,当仅提及类名本身(例如M::M::M)时,情况略有不同.如果这样的引用发生在对函数的引用也可能正确的地方,则采用语法来引用构造函数.但是,在仅类型的上下文中,即使这样的引用也是有效的.例:

M::M::M m;  // illegal, M::M interpreted as reference to constructor

struct D : public M::M::M  // legal, a function could not be references here, so M::M::M means M
{};
Run Code Online (Sandbox Code Playgroud)


Tar*_*ama 9

这是因为注入类名称:

(N3337) [class]/2:在看到类名后立即将类名插入到作用域中.类名也插入到类本身的范围内; 这被称为注入类名.出于访问检查的目的,inject-class-name被视为公共成员名称.[...]

所以你可以任意嵌套这些,他们也可以使用派生类型:

struct A { using type = int; };
struct B : public A {};

using foo = B::B::B::A::A::A::type;
Run Code Online (Sandbox Code Playgroud)

请注意,在这种情况下A[::A]*::A,可以考虑将inject-name命名为构造函数:

[class.qual]/2:在查找中,构造函数是可接受的查找结果,并且嵌套名称说明符指定一个类C:

- 如果在查找嵌套名称说明符之后指定C的名称是C(第9章)的inject -name-name ,或者

- [...]

而是将名称视为命名类的构造函数C.

  • *"请注意,在`A [:: A]*:: A`的情况下,注入类名可以被认为是命名构造函数:"*Ib4自然后续欺骗:是的,铿锵倾向弄错了.参见例如[this](/sf/ask/2077701461/). (2认同)