什么时候实例化模板类的成员函数? [英] When are member functions of a templated class instantiated?

查看:25
本文介绍了什么时候实例化模板类的成员函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下示例:

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. 为什么编译器对仅在文件末尾定义的 ABC 类感到满意?
  2. 为什么在声明 Derived 时不需要定义,在声明全局 foo 函数时也不需要定义?
  3. 什么时候实例化模板化类的成员函数?即使函数是显式内联的,在 foo() 中调用该函数后,该函数似乎也被实例化(在文件末尾).
  4. 这种行为是标准的 C++ 吗?如果是,是否取决于使用的 C++ 版本?
  1. Why is the compiler happy with class ABC only defined at the end of the file?
  2. Why is the definition not needed when declaring Derived, nor when declaring the global foo function?
  3. When are member functions of a templated class instantiated? Even when the function is made explicit inline, the function seems to be instantiated (at the end of the file) after the function is called in foo ().
  4. Is this behaviour standard C++? If so, does it depends on the C++ version used?

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

Note that fooDerived generates an error as expected: the class should be (fully) defined before it is used.

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

测试环境:

  • MSVC(但我对跨平台合规性很感兴趣.)
  • 它似乎可以在三个主要编译器(GCC、CLang 和 MSVC)上运行(除了 DEF def; 按预期):https://godbolt.org/z/z_c7mc
  • MSVC (but I'm interested in cross platform compliance.)
  • It seems to work (except for DEF def; as expected) on the three main compilers (GCC, CLang AND MSVC): https://godbolt.org/z/z_c7mc

推荐答案

模板化类的成员函数什么时候实例化?

When are member functions of a templated class instantiated?

类模板特化的成员函数的声明与类特化一起实例化,但定义仅在需要时实例化.通常在调用成员函数时.只要没有使用成员函数,定义就可能没有被实例化.

The declaration of a class template specialization's member function is instantiated along with the class specialization, but the definition is only instantiated when needed. Usually when the member function is called. So long as nothing uses the member function, the definition may go un-instantiated.

您的示例调用成员函数,因此必须实例化定义.

Your example calls the member function, so the definition must be instantiated.

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

There may however be multiple points of instantiation for a member function of a specialization. One is immediately before being used, but an additional one (that is always added) is at the end of the translation unit

[temp.point](强调我的)

8 一个函数模板的特化,一个成员函数模板,或成员函数或类的静态数据成员模板可能有多个实例化点翻译单元,除了实例化点如上所述,对于任何这样的专业化,有一个点翻译单元内的实例化,翻译结束单元也被认为是一个实例化点.专攻一个类模板最多有一个实例化点翻译单位.任何模板的特化可能有以下几点在多个翻译单元中实例化.如果两个不同的点实例化赋予模板特化不同的含义根据单一定义规则,程序格式错误,没有需要诊断.

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 中是不完整的,而在另一个中它已经完成了.在上面的段落下,您的程序格式错误,不需要诊断.编译器可以对违规保持沉默,同时发出一些似乎的代码.但这并不能使程序有效.如果将来更新标准以要求在这种情况下进行诊断,则非法代码将无法构建.如果编译器希望诊断它,它现在甚至可能会失败.

Which brings me to the next point,fooBase has two points of instantiations in the translation unit you show. In one ABC is incomplete, while in the other it has been completed. Under the paragraph above, your program is ill-formed, no diagnostic required. A compiler can be silent about the violation, all the while emitting some code the seems to work. But that does not make the program valid. If the standard is updated in the future to require a diagnostic in this case, the illegal code will fail to build. It may even fail now if compilers wish to diagnose it.

这篇关于什么时候实例化模板类的成员函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆