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