2017-06-19 32 views
2

考虑到这种代码: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)专业化?

我的猜测是,当声明专业化时,已经声明了模板,并从那些最“专业的”(其参数与这个专业化“最接近”)被选择。它是否正确?另外,您能否指出我在标准中指定的位置?

回答

3

它会打印“第一个”,因为声明的顺序会影响您实际专用的模板。

你的例子有两个函数模板,它们重载相同的名字。在第一种情况下,您专门致力于void f(T p),因为它是目前为止唯一可见的模板。

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

在一项声明,其声明符-ID是指 函数模板的特化,模板参数推导进行到 查明该声明指专业化。 具体来说,这是针对显式实例化,显式 专业化,和某些朋友声明。 [...]

而且包括功能模板的部分排序。但是,部分排序仅适用于您引入专业化时可用的函数模板声明。

,标准警告在[temp.expl.spec/7]

明确的专业化声明的位置函数模板,[...],可以根据显式专业化 声明的相对定位以及它们在如上下文指定的翻译单元 中的实例化点的相对定位来影响程序是否格式良好 。在写专业时,请注意 的位置;或者让它编译成这样的尝试 以点燃它的自焚。

+0

因此,从专业化之前声明的模板函数中,使用偏序排序来选择“正确的一个”? – user42768

+0

@ user42768 - 通过模板参数推导*和*部分排序,是的。 – StoryTeller