模板演绎似乎不对

时间:2013-06-12 07:32:18

标签: c++ templates

推断的模板似乎是错误的,为什么(c)被调用而不是(b)?

#include <iostream>
using namespace std;
template<class T> void f(T){cout << "f(T)";}//(a)
template<> void f<>(int*){cout << "f(int*)";}//(b)
template<class T> void f(T*){cout << "f(T*)";}//(c)
//void f(int*){cout <<"POD:f(int*)";}//(d)

int main(int argc,char*argv[])
{
    int p = 1;
    f(&p);
    cout <<endl;
    return 0;
}

输出

  

f(T*)

2 个答案:

答案 0 :(得分:3)

好的,让我们先说清楚我们先拥有的东西。

(a)是一个功能模板。 (b)是该功能模板的专业化。 (c)是另一个重载(a)的函数模板。

当您编写f(&p)时,需要考虑两个重载:两个函数模板,(a)和(c)。在(c)中,T*比(a)中的T更专业,因此(c)被选中。

现在让我们考虑一下注释(d)。这不是函数模板(a)的特化,而是额外的重载。要解决f(&p)调用,现在需要考虑三个重载。 (d)不是模板,并且int*&p的类型相匹配,因此它会被其他两个选中。

答案 1 :(得分:0)

模板专业化必须在模板之后。 在这种情况下,它看起来像这样:

template<class T> void f(T){cout << "f(T)";}//(a) // Template 1
template<> void f<>(int*){cout << "f(int*)";}//(b) // Specialization of template 1
template<class T> void f(T*){cout << "f(T*)";}//(c) // Template 2, conceals template 1

因此,您可以实例化模板2。 正确的做法是:

template<class T> void f(T*){cout << "f(T*)";} // Template 1
template<class T> void f(T){cout << "f(T)";} // Template 2
template<> void f<>(int*){cout << "f(int*)";} // Specialization of the template 1

输出:

f(int*)