5

考虑到这段代码:

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);will output之类的调用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) 特化?

我的猜测是,在声明特化时,会考虑已声明的模板,并从那些最“特化”(其参数与该特化“最接近”的)中选择。这个对吗?另外,您能否指出标准中指定的位置?

4

1 回答 1

5

它打印“First”,因为声明的顺序会影响您实际上专门研究的模板。

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

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

在其 declarator-id 指代函数模板的特化的声明中,执行模板参数推导以识别该声明所指的特化具体来说,这是针对显式实例化、式特化和某些友元声明完成的。[...]

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

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

函数模板的显式特化声明的放置,[...],可以根据显式特化声明的相对定位及其在翻译单元中的实例化点(如上文和下文指定)影响程序是否格式正确。编写专业时,请注意其位置;或者让它编译将是一种试炼,以点燃它的自焚。

于 2017-06-19T07:17:13.903 回答