考虑此代码:
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
。
我读到了函数模板重载解析发生的方式:首先,解析只考虑非模板函数和底层基本模板。在&#34;最专业的&#34;选择一个,如果它是一个模板函数,并且它具有对推导(或明确指定)的参数的特化,则调用该特化。
现在我的问题是:如何确定哪个底层基本模板一个函数是一个特化?在我的例子中,哪个函数模板重载((1)或(3))是(2)一个特化?
我的猜测是,当声明一个特化时,会考虑已经声明的模板,并从那些最常用的模板中考虑#34; (选择参数为&#34;最接近&#34;此专业化)。它是否正确?另外,您能指出我在标准中指定的位置吗?
答案 0 :(得分:3)
它打印&#34;第一&#34;因为声明的顺序会影响你实际上专门化的模板。
您的示例有两个函数模板,它们重载相同的名称。在第一种情况下,您会专注void f(T p)
,因为它是目前为止看到的唯一模板。
在第二种情况下,它是void f(T* p)
专门的。{{1}}。所以是的,你的猜测是正确的。具体内容为[temp.deduct.decl/1]:
在声明中,声明者id指的是a的特化 函数模板,执行模板参数推导 确定声明所指的专业化。 具体来说,这是为了显式实例化,显式 专业化,和某些朋友声明。 [...]
这包括功能模板的部分排序。但是,部分排序仅适用于您引入专业化时可用的函数模板声明。
标准警告[temp.expl.spec/7]:
功能模板的显式专业化声明的放置,[...],会影响程序是否格式正确 根据显式专业化的相对定位 声明及其在翻译单元中的实例化要点 如上下文所述。写专业时,请 小心它的位置;或者使它编译将是这样的试验 点燃自焚。