This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 116a. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-12-19
[Adopted at the February, 2016 meeting.]
Three points have been raised where the wording in 13.9.2 [temp.inst] may not be sufficiently clear.
A class template specialization is implicitly instantiated... if the completeness of the class type affects the semantics of the program...
It is not clear what it means for the "completeness... [to affect] the semantics." Consider the following example:
template<class T> struct A; extern A<int> a; void *foo() { return &a; } template<class T> struct A { #ifdef OPTION void *operator &() { return 0; } #endif };
The question here is whether it is necessary for template class A to declare an operator & for the semantics of the program to be affected. If it does not do so, the meaning of &a will be the same whether the class is complete or not and thus arguably the semantics of the program are not affected.
Presumably what was intended is whether the presence or absence of certain member declarations in the template class might be relevant in determining the meaning of the program. A clearer statement may be desirable.
If the overload resolution process can determine the correct function to call without instantiating a class template definition, it is unspecified whether that instantiation actually takes place.
The intent of this wording, as illustrated in the example in that paragraph, is to allow a "smart" implementation not to instantiate class templates if it can determine that such an instantiation will not affect the result of overload resolution, even though the algorithm described in Clause 12 [over] requires that all the viable functions be enumerated, including functions that might be found as members of specializations.
Unfortunately, the looseness of the wording allowing this latitude for implementations makes it unclear what "the overload resolution process" is — is it the algorithm in Clause 12 [over] or something else? — and what "the correct function" is.
If an implicit instantiation of a class template specialization is required and the template is declared but not defined, the program is ill-formed.
Here, it is not clear what conditions "require" an implicit instantiation. From the context, it would appear that the intent is to refer to the conditions in paragraph 4 that cause a specialization to be instantiated.
This interpretation, however, leads to different treatment of template and non-template incomplete classes. For example, by this interpretation,
class A; template <class T> struct TA; extern A a; extern TA<int> ta; void f(A*); void f(TA<int>*); int main() { f(&a); // well-formed; undefined if A // has operator &() member f(&ta); // ill-formed: cannot instantiate }
A different approach would be to understand "required" in paragraph 6 to mean that a complete type is required in the expression. In this interpretation, if an incomplete type is acceptable in the context and the class template definition is not visible, the instantiation is not attempted and the program is well-formed.
The meaning of "required" in paragraph 6 must be clarified.
Notes on 10/01 meeting:
It was felt that item 1 is solved by addition of the word "might" in the resolution for issue 63; item 2 is not much of a problem; and item 3 could be solved by changing "required" to "required to be complete".
Proposed resolution (January, 2016):
Change 13.9.2 [temp.inst] paragraph 1 as follows, moving the note and example from paragraph 6 and breaking it into two paragraphs:
Unless a class template specialization has been explicitly instantiated (13.9.3 [temp.explicit]) or explicitly specialized (13.9.4 [temp.expl.spec]), the class template specialization is implicitly instantiated when the specialization is referenced in a context that requires a completely-defined object type or when the completeness of the class type affects the semantics of the program. [Note: In particular, if the semantics of an expression depend on the member or base class lists of a class template specialization, the class template specialization is implicitly generated. For instance, deleting a pointer to class type depends on whether or not the class declares a destructor, and a conversion between pointers to class type depends on the inheritance relationship between the two classes involved. —end note] [Example:
template<class T> class B { /* ... */ }; template<class T> class D : public B<T> { /* ... */ }; void f(void*); void f(B<int>*); void g(D<int>* p, D<char>* pp, D<double>* ppp) { f(p); // instantiation of D<int> required: call f(B<int>*) B<char>* q = pp; // instantiation of D<char> required: // convert D<char>* to B<char>* delete ppp; // instantiation of D<double> required }—end example] If a class template has been declared, but not defined, at the point of instantiation (13.8.4.1 [temp.point]), the instantiation yields an incomplete class type (6.8 [basic.types]). [Example:
template<class T> class X; X<char> ch; // error: incomplete type X<char>
—end example] [Note: Within a template declaration, a local class (11.6 [class.local]) or enumeration and the members of a local class are never considered to be entities that can be separately instantiated (this includes their default arguments, exception-specifications, and non-static data member initializers, if any). As a result, the dependent names are looked up, the semantic constraints are checked, and any templates used are instantiated as part of the instantiation of the entity within which the local class or enumeration is declared. —end note]
The implicit instantiation of a class template specialization causes the implicit instantiation of the declarations, but not...
Delete 13.9.2 [temp.inst] paragraph 6, moving the note and example to paragraph 1 as shown above:
A class template specialization is implicitly instantiated if the class type is used in a context that requires a completely-defined object type or if the completeness of the class type might affect the semantics of the program. [Note: In particular, if the semantics of an expression depend on the member or base class lists of a class template specialization, the class template specialization is implicitly generated. For instance, deleting a pointer to class type depends on whether or not the class declares a destructor, and conversion between pointer to class types depends on the inheritance relationship between the two classes involved. —end note] [Example:template<class T> class B { /* ... */ }; template<class T> class D : public B<T> { /* ... */ }; void f(void*); void f(B<int>*); void g(D<int>* p, D<char>* pp, D<double>* ppp) { f(p); // instantiation of D<int> required: call f(B<int>*) B<char>* q = pp; // instantiation of D<char> required: // convert D<char>* to B<char>* delete ppp; // instantiation of D<double> required }
—end example]
Change 13.9.2 [temp.inst] paragraph 7 as follows:
If the function selected by overload resolutionprocess(12.2 [over.match]) candetermine the correct function to callbe determined without instantiating a class template definition, it is unspecified whether that instantiation actually takes place. [Example:...
Delete 13.9.2 [temp.inst] paragraphs 8-9:
If an implicit instantiation of a class template specialization is required and the template is declared but not defined, the program is ill-formed. [Example:template<class T> class X; X<char> ch; // error: definition of X required
—end example]
The implicit instantiation of a class template does not cause any static data members of that class to be implicitly instantiated.