【问题标题】:Is it legal to use template class name in derived class without template arguments?在没有模板参数的派生类中使用模板类名是否合法?
【发布时间】:2019-06-21 12:57:41
【问题描述】:

以下代码使用clang++ 8.0.0g++ 9.1.0 都可以正常编译(编译标志为-Wall -Wextra -Werror -pedantic-errors):

template <typename>
struct Base
{
};

struct Derived : Base<int>
{
    Base base()
    {
        return Base();
    }
};

int main()
{
}

这是这些编译器中的错误还是 C++ 标准的一个特性?

【问题讨论】:

  • 要认识到的重要一点是 Base 是一个类,而不是模板类。编译器使用模板构建一个类,其中类型名 T 被模板化参数替换。所以,Base 是一个模板,而 Base 是模板生成的一个类。这意味着您可以在通常使用类的任何地方使用 Base 。这包括变量声明,或者如您所见,继承。
  • @Chipster 我认为您错过了问题中的“...没有模板参数”。
  • 您发布的代码使用了它们,所以是的。我一定是误会了。您是在问为什么您发布的代码可以编译,或者为什么另一个 sn-p 可以或无法编译?
  • @Chipster 不,我发布的代码没有使用它们。查看方法Derived::base()的定义。
  • 啊。我明白你了现在。不知何故,我错过了那部分。我认为这是一个关于继承的问题。我猜错了。

标签: c++ templates inheritance language-lawyer c++17


【解决方案1】:

injected-class-name

Base&lt;T&gt; 内部,Base 指的是(在某些情况下)Base&lt;T&gt;

Derived 也会使用注入的类名。

【讨论】:

  • 嗯。我认为它仅适用于模板化上下文,而不适用于从显式类模板特化派生的类。
【解决方案2】:

这段代码很好。在Derived 内部,Base 类将引用Base&lt;int&gt;因为 Derived 继承自Base&lt;int&gt;。是的,这是合法的。

标准:

14.6.1.1: 与普通(非模板)类一样,类模板具有注入类名(第 9 条)。注入的类名可以用作模板名或类型名。当它与模板参数列表一起使用时,作为模板模板参数的模板参数,或作为朋友类模板声明的详细类型说明符中的最终标识符,它指的是类模板本身.否则,它相当于模板名称后跟 .

中包含的类模板的模板参数

还有:

3.4.3:一个类的注入类名(第 9 条)也被认为是该类的成员,用于名称隐藏和查找。

最后一句话做到了。简而言之,A&lt;B&gt; 引入了隐藏的“别名”A = A&lt;B&gt;,但前提是A 不使用&lt;&gt;。举个例子,它在基类中引入,派生类继承基类的所有成员。

【讨论】:

  • 能否提供标准参考?
  • 我还要添加[basic.lookup]/3,这意味着注入的类名像其他公共成员一样继承。
猜你喜欢
  • 2018-11-05
  • 1970-01-01
  • 2021-04-13
  • 1970-01-01
  • 1970-01-01
  • 2016-04-12
  • 1970-01-01
相关资源
最近更新 更多