C++ CRTP virtual function point of instantiation

前端 未结 2 765
长发绾君心
长发绾君心 2021-01-11 11:51

I\'m trying to understand if a simple CRTP pattern is valid by the standard.

The code below compiles and works as expected (on clang).

But my understanding o

2条回答
  •  小鲜肉
    小鲜肉 (楼主)
    2021-01-11 12:56

    This appears to be a result of the compiler delaying instantiation of CRTP::DoSomething() until the end of the translation unit, as it is allowed to do (see CWG issue 993).

    CRTP is definitely instantiated right before the definition of Derived (§14.6.4.1 [temp.point]/p4, all quotes are to N3936):

    For a class template specialization, a class member template specialization, or a specialization for a class member of a class template, if the specialization is implicitly instantiated because it is referenced from within another template specialization, if the context from which the specialization is referenced depends on a template parameter, and if the specialization is not instantiated previous to the instantiation of the enclosing template, the point of instantiation is immediately before the point of instantiation of the enclosing template. Otherwise, the point of instantiation for such a specialization immediately precedes the namespace scope declaration or definition that refers to the specialization.

    Whether CRTP::DoSomething() is required to be instantiated at all depends on the meaning of the phrase referenced in a context that requires the member definition to exist (§14.7.1 [temp.inst]/p2). All non-pure virtual functions are odr-used (§3.2 [basic.def.odr]/p2), and "every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program" (§3.2 [basic.def.odr]/p4); whether that counts as "referenced in a context that requires the member definition to exist" is unclear.

    (Even if it's not required to be instantiated, however, the compiler is still free to instantiate it per §14.7.1 [temp.inst]/p11 - "It is unspecified whether or not an implementation implicitly instantiates a virtual member function of a class template if the virtual member function would not otherwise be instantiated.".)

    If CRTP::DoSomething() is indeed instantiated, then the situation is covered by §14.6.4.1 [temp.point]/p5 and p8 (emphasis mine):

    5 If a virtual function is implicitly instantiated, its point of instantiation is immediately following the point of instantiation of its enclosing class template specialization.

    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 (3.2), the program is ill-formed, no diagnostic required.

    That is, it has two points of instantiation, one right after CRTP< Derived, Base >'s point of instantiation, and one at the end of the translation unit. In this case, at the two points of instantiations name lookup for typename T::Type would produce different results, so the program is ill-formed, no diagnostic required.

提交回复
热议问题