【问题标题】:Why isn't `typename` required for a base class that is a nested type?为什么嵌套类型的基类不需要“typename”?
【发布时间】:2020-01-12 23:32:26
【问题描述】:

我很惊讶地发现,当依赖类型作为基类出现时,不需要添加typename

struct B {};

struct wr
{ typedef B type; };

template<class T>
struct A : T::type
{};

int main()
{
    A<wr> a;
    (void)a;
}

为什么typename 前面不需要T::type

【问题讨论】:

    标签: c++ templates inheritance


    【解决方案1】:

    为什么typename 前面不需要T::type

    因为你不能从一个值继承。您使用 typename 告诉编译器给定的嵌套标识符是一种类型,但对于继承,无论如何都必须是这种情况,因此您可以省略它 - 这就是语言为 typename- 基本规则提供例外的原因-说明符。来自cppreference(强调我的):

    typename 从属名称消歧器

    在模板的声明或定义中,包括别名模板,不是当前实例化成员且依赖于模板参数的名称不被视为类型,除非使用关键字 typename 或 除非它已经被确定为类型名称,例如使用 typedef 声明或用于命名基类

    请注意,我们将获得更多可以省略typename 的地方,请参阅P0634

    【讨论】:

      【解决方案2】:

      正如其他人所说,这是一种特殊情况。引用这个标准:

      [温度分辨率]

      5 在 class-or-decltype 或 详细说明类型说明符被隐式假定为命名一个类型, 不使用 typename 关键字。在嵌套名称说明符中 立即包含一个嵌套名称说明符,该说明符取决于 模板参数,标识符或 simple-template-id 是隐式的 假定命名一个类型,而不使用 typename 关键字。 [ 注意:这些语法不允许使用 typename 关键字 结构体。 — 尾注 ]

      随着 C++20 的到来,需要typename 的例外情况会更多。

      【讨论】:

      • 还会有哪些例外?
      • @0x499602D2 - 函数返回类型、各种 *_cast 运算符的类型参数和默认模板参数。 The paper 有示例和详细信息。
      【解决方案3】:

      如果你需要告诉编译器期待一个类型而不是其他东西,你只需要使用typename

      由于只能继承一个类型,所以没有歧义,所以typename是多余的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-02-24
        • 2020-09-11
        • 1970-01-01
        • 1970-01-01
        • 2010-11-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多