When are member functions of a templated class instantiated?

橙三吉。 提交于 2020-01-01 17:56:07

问题


Consider the following example:

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 {};

Question(s)

  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?

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

Note that it is not necessary to answer all the questions separately, as they are rather different formulations of the same question.

Tested environment:

  • 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

回答1:


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] (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.

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.



来源:https://stackoverflow.com/questions/59435038/when-are-member-functions-of-a-templated-class-instantiated

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!