为什么模板类允许无法编译的成员函数?

qea*_*adz 16 c++ templates

class P
{
};

template< typename P >
class C : public P
{
  public:
  void f()
  {
    P::f();
  }
};

int main() {
  C<P> c1;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

为了防止我的问题留下任何误解的空间,这是一个代码示例.如果C没有模板,但是从继承P直接,那么样品将无法编译,因为明确的功能f()试图呼吁基类的功能P是不存在的.

但是如果C是模板化的话,那么只有在f()实际调用时才会被拾取.

我想知道为什么会有这种差异.在这两种情况下f()都是死代码并且无论如何都会被剥离,但程序在非模板场景中是不正确的.

Bau*_*gen 19

实际上,你发布的程序并不是格式错误.而"隐式实例化" C<P> c1;实例化所有成员声明,

当在需要成员定义存在的上下文中引用特化时,隐式实例化成员的特化

[N4140,14.7.1(2)]由于你从不使用C<P>::f,因此永远不需要它的定义,因此从未实例化.

这与"显式实例化"不同

template class C<P>;
Run Code Online (Sandbox Code Playgroud)

这将实例化所有成员的定义,C<P>从而导致错误.


sba*_*bbi 8

因为允许仅使用实际形成良好的函数是有意义的.

vector::push_back(const T&),这需要T是可复制的.但vector即使T是可移动的非可复制类型,您仍然可以使用大部分内容.


Cia*_*Pan 5

在模板类中,identifier P是模板参数typename,它引用class P之前定义的.所以你不能说不P::f()存在,因为你不知道哪个类将替代参数P.

稍后,当您调用模板来声明c1变量时,不需要该函数,因此没有"死代码" - 只有一个模板,它从未扩展为实际代码.