Function template: point of instantiation and declaration

Viewed 159

I have a question on code from Stroustrup C++ 4th Ed Page 749-750. This code is trying to show point of instantiation binding. Stroustrup says just before this code that "Each use of a template for a given set of template arguments defines a point of instantiation. For a function template, that point (of instantiation) is in the nearest global or namespace scope enclosing its use, just after the declaration that contains that use.".

void g(int);

template<typename T> 
void f(T a)
{
   g(a); // g is bound at a point of instantiation
}

void h(int i) 
{
   extern void g(double);
   f(i); 
}
// point of declaration for f<int>

Questions regarding this code:

  • Is the point of instantiation f(i)? It is a use of a template for a given set of arguments. If not what is it?
  • Stroustrup comments that the "point of declaration" for f<int> is after h() {}. Is the point of declaration different than point of instantiation?
1 Answers

All standard references below refers to N4659: March 2017 post-Kona working draft/C++17 DIS.


Is the point of instantiation f(i)? It is a use of a template for a given set of arguments. If not what is it?

No, whilst f(i), in this example, refers to the f<int> specialization in a way that requires it to exist, the point of instantiation of the specialization immediately follows the definition of void h(int), given that the definition of void h(int) is the first definition that refers to the specialization, as per [temp.point]/1:

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


Stroustrup comments that the "point of declaration" for f<int> is after h() {}. Is the point of declaration different than point of instantiation?

Yes, the point of declaration is different from the point of instantiation. From [temp.inst]/4 and [temp.inst]/8:

[temp.inst]/4 Unless a function template specialization has been explicitly instantiated or explicitly specialized, the function template specialization is implicitly instantiated when the specialization is referenced in a context that requires a function definition to exist. [...]

[temp.inst]/8 If a function template or a member function template specialization is used in a way that involves overload resolution, a declaration of the specialization is implicitly instantiated ([temp.over]).

The former also depends on overload resolution, whereas the a function template can be instantiated without it being involved in overload resolution (e.g. explicit instantiations). As is covered by [temp.point]/8, a specialization for a function template may have multiple points of instantiations within a translation unit, but a declaration for the given specialization is naturally only generated once within a single translation unit (as is covered above: at first use in the context of overload resolution).

In your particular example, the invocation of f(i) in h will both implicitly instantiate f<int> as well as lead to the declaration of f<int>, as the invocation involves overload resolution, but these mechanisms are governed by different, albeit related, rules.

Related