【问题标题】:Why is decltype(class::class::class::member) valid [duplicate]为什么 decltype(class::class::class::member) 有效[重复]
【发布时间】:2016-10-05 17:53:51
【问题描述】:

我偶然注意到这段代码可以正确编译和工作:

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) &lt;=&gt; decltype(M::some_int))?

class::class::...::member 可以使用此模式的其他哪些构造?

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

【问题讨论】:

  • 哦,男孩..让赞成票涌入显然是duplicate的东西。

标签: c++ c++11 decltype


【解决方案1】:

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

[Live example]

请注意,当仅引用类名本身时(例如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
{};

【讨论】:

    【解决方案2】:

    这是因为 injected-class-name

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

    所以你可以任意嵌套它们,它们也可以与派生类型一起使用:

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

    注意,在A[::A]*::A的情况下,可以考虑注入的类名来命名构造函数:

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

    — 如果在嵌套名称说明符之后指定的名称,当在 C 中查找时,是注入的类名称 C(第 9 条),或

    ——[...]

    该名称被认为是命名类C的构造函数。

    【讨论】:

    • "注意,在A[::A]*::A的情况下,注入的类名可以认为是构造函数的名称:" ib4自然后续骗子:是的,clang 往往会出错。参见例如this.
    猜你喜欢
    • 1970-01-01
    • 2012-08-03
    • 1970-01-01
    • 1970-01-01
    • 2021-09-23
    • 1970-01-01
    • 1970-01-01
    • 2013-11-08
    • 1970-01-01
    相关资源
    最近更新 更多