函数模板:实例化和声明点

Function template: point of instantiation and declaration

我对 Stroustrup C++ 第 4 版第 749-750 页的代码有疑问。此代码试图显示实例化绑定点。 Stroustrup 在这段代码之前说 “对给定的模板参数集,模板的每次使用都定义了一个实例化点。对于函数模板,该点(实例化)位于最近的全局或命名空间范围内在包含该用途的声明之后附上它的用途。".

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>

关于此代码的问题:

以下所有标准参考均指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?

否,而 f(i),在此示例中,指的是 f<int> 特化 以需要它存在的方式 ,实例化点专业化的定义紧跟在 void h(int) 之后, 鉴于 void h(int) 的定义是第一个引用专业化的定义,根据 [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?

是的,声明点与实例化点不同。来自 [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]).

前者也依赖于重载决议,而函数模板可以在不参与重载决议的情况下被实例化(例如显式实例化)。正如 [temp.point]/8 所涵盖的那样,函数模板的特化可能在翻译单元中有多个实例化点,但是给定特化的声明自然只会在单个翻译单元中生成一次(如上文所述:首先在重载解析的上下文中使用。

在您的特定示例中,hf(i) 的调用将隐式实例化 f<int> 并导致 f<int> 的声明,作为调用涉及重载决议,但这些机制由不同但相关的规则管理。