我意外地注意到这段代码编译并正常工作:
struct M { int some_int; };
static_assert(std::is_same<
decltype(M::M::M::M::some_int) /* <- this */,
int>::value, "Types must be int");
为什么这是正确的(decltype(M::M::M::M::some_int) <=> decltype(M::some_int)
)?
可以使用class::class::...::member
这个模式的其他构造吗?
编译器:用于x86的Microsoft(R)C / C ++优化编译器版本19.00.23824.1
答案 0 :(得分: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
{};
答案 1 :(得分:9)
这是因为 inject-class-name :
(N3337) [class]/2:
在看到类名后立即将类名插入到作用域中。 类名也插入到类本身的范围内;这被称为注入类名。 出于访问检查的目的,inject-class-name被视为公共成员名称。 [...]
所以你可以随意嵌套这些,并且他们也可以使用派生类型:
struct A { using type = int; };
struct B : public A {};
using foo = B::B::B::A::A::A::type;
请注意,对于A[::A]*::A
,可以考虑使用inject-name来命名构造函数:
[class.qual]/2:
在查找中,构造函数是可接受的查找结果,并且嵌套名称说明符指定 一个班级C
:- 如果在
C
中查找时,在嵌套名称说明符之后指定的名称是注入类名C
(第9条)或- [...]
而是将名称视为命名类
C
的构造函数。