模板化 class 的成员函数何时实例化?

When are member functions of a templated class instantiated?

考虑以下示例:

template<typename T>
class Base
{
public:
  inline void fooBase ()
  {
    T t; // The following error only occurs when class ABC is not defined at the end of the file: "error: t uses undefined class ABC"
  }
protected:
};

class ABC;
class DEF;

class Derived : public Base<ABC>
{
public:
  void fooDerived ()
  {
    DEF def; // error: def uses undefined class DEF
  }
};

Derived derived;
void foo ()
{
  derived.fooBase ();
}

class ABC {};
class DEF {};

问题

  1. 为什么编译器对 class ABC 仅定义在文件末尾感到满意?
  2. 为什么在声明 Derived 时不需要定义,在声明全局 foo 函数时也不需要定义?
  3. 模板化class的成员函数何时实例化?即使该函数是显式内联的,该函数似乎在 foo ().
  4. 中调用该函数后被实例化(在文件末尾)
  5. 这种行为是标准的 C++ 吗?如果是,是否取决于所使用的 C++ 版本?

请注意,fooDerived 会按预期生成错误:class 应在使用前(完全)定义。

请注意,没有必要单独回答所有问题,因为它们是同一问题的不同表述。

测试环境:

When are member functions of a templated class instantiated?

class 模板特化的成员函数的 声明 与 class 特化一起实例化,但是 定义 仅在需要时实例化。通常在调用成员函数时。只要没有使用成员函数,定义就可以取消实例化。

你的例子调用了成员函数,所以必须实例化定义。

然而,一个特化的成员函数可能有多个实例化点。一个在使用之前,但另一个(总是添加)在翻译单元的末尾

[temp.point] (emphasis mine)

8 A specialization for a function template, a member function template, or of a member function or static data member of a class template may have multiple points of instantiations within a translation unit, and in addition to the points of instantiation described above, for any such specialization that has a point of instantiation within the translation unit, the end of the translation unit is also considered a point of instantiation. A specialization for a class template has at most one point of instantiation within a translation unit. A specialization for any template may have points of instantiation in multiple translation units. If two different points of instantiation give a template specialization different meanings according to the one-definition rule, the program is ill-formed, no diagnostic required.

这让我想到了下一点,fooBase 在您展示的翻译单元中有两个实例化点。在一个 ABC 中是不完整的,而在另一个中它已经完成了。根据上面的段落,您的程序格式错误,不需要诊断。编译器可以对违规保持沉默,同时发出一些 似乎 可以工作的代码。但这并不能使程序有效。如果将来更新标准要求在这种情况下进行诊断,则非法代码将无法构建。如果编译器希望对其进行诊断,它现在甚至可能会失败。