C++函数模板专用化和重载



考虑以下代码:

template <class T>
void f(T p) {           //(1)
cout << "Second" << endl;
}
template <>
void f(int *p) {        //(2)
cout << "Third" << endl;
}

template <class T>
void f(T* p) {          //(3)
cout << "First" << endl;
}

诸如int *p; f(p);之类的调用将输出First

如果声明的顺序发生更改,如下所示:

template <class T>
void f(T* p) {          //(3)
cout << "First" << endl;
}

template <class T>
void f(T p) {           //(1)
cout << "Second" << endl;
}
template <>
void f(int *p) {        //(2)
cout << "Third" << endl;
}

相同的调用(int *p; f(p);)将输出Third

我阅读了函数模板重载解析的发生方式:首先,解析仅考虑非模板函数底层基本模板。在选择了"最专业"的函数之后,如果它是一个模板函数,并且它对推导(或明确指定)的参数具有专用化,则称为该专用化。

现在我的问题是:如何确定函数是哪个底层基本模板的专用化?在我的示例中,哪个函数模板重载((1)或(3))是(2)专用化?

我的猜测是,当声明专业化时,会考虑已经声明的模板,并从那些最"专业化"的模板(其参数"最接近"此专业化)中选择。这是对的吗?另外,您能否指出标准中指定的位置?

它打印"First",因为声明的顺序会影响您实际上专攻的模板。

您的示例有两个函数模板,它们重载相同的名称。在第一种情况下,您专门化void f(T p),因为它是迄今为止看到的唯一模板。

在第二种情况下,void f(T* p)是专门的。所以是的,你的猜测是正确的。具体内容在 [temp.deduct.decl/1]:

在其声明符 ID 引用 函数模板,模板参数推导执行 确定声明所指的专业化具体来说,这是针对显式实例化完成的,显式 专业和某些朋友声明。[...]

这包括函数模板的部分排序。但是,部分排序仅适用于引入专用化时的可用函数模板声明。

标准在 [temp.expl.spec/7] 处发出警告:

函数模板 [...] 的显式专用化声明的放置 可能会影响程序的格式是否正确 根据明确专业化的相对定位 声明及其在翻译单元中的实例化点 如上文和下文所述。在撰写专业时,请 注意它的位置;或者让它编译将是这样的试验 至于点燃它的自焚。

最新更新