说我的代码如下:
#include <iostream>
template<typename>
void printnum(int i) {
std::cout<<"in int method:"<<std::endl;
std::cout<< i<<std::endl;
}
template<typename>
void printnum(char i) {
std::cout<<"in char method:"<<std::endl;
std::cout<<(int)i<<std::endl;
}
int main() {
printnum<int>(2);
printnum<char>(3);
}
输出:
in int method:
2
in int method:
3
我对此测试代码的意图是确认/不确认我对template<typename>
模板的使用的理解(自然)。由于没有给出模板类型的参数,我认为这样的结构有助于重载解析。也就是说,没有模板注释,很明显我会得到上面的输出。但是使用模板注释,我认为我可能会强制编译器采用(3-call
)char-variant
函数的printnum()
,这不是情况下。
所以我的一般问题是: template<typename>
构造的用途是什么?
答案 0 :(得分:1)
对于所有类型T
,您都有一系列函数,将int
作为参数(T
和int
之间没有关联);顺便说一下,所有人都在做同样的事情。对于所有类型T
,您都有另一个函数系列,将char
作为参数。
省略名称T
并未在您的功能模板上传达任何神奇的属性:template <typename T> void f();
和template <typename> void f();
完全相同。
printnum<int>(2)
实例化第一个族中的一个函数(用于T == int
),以及第二个族中的一个函数,并对它们执行重载解析。来自第一个家庭的功能获胜。与printnum<char>(3)
您可能正在考虑模板专业化:
template <typename T> void printnum(T);
template<>
void printnum(int i) {
std::cout<<"in int method:"<<std::endl;
std::cout<< i<<std::endl;
}
template<typename>
void printnum(char i) {
std::cout<<"in char method:"<<std::endl;
std::cout<<(int)i<<std::endl;
}
这里有一系列功能。实际上只定义了这个系列的两个成员(尝试使用任何其他实例化会导致链接器错误)。模板参数明确地选择该族的特定成员;因为只有一个可行的函数可以调用,所以不会执行重载决策。
答案 1 :(得分:1)
主要原因是允许参数明确专门化。考虑:
#include <iostream>
template<typename> void printnum(int i);
template<>
void printnum<int>(int i) {
std::cout<<"in int method: "<<i<<std::endl;
}
template<>
void printnum<char>(int i) {
std::cout<<"in char method: "<<i<<std::endl;
}
int main() {
printnum<int>(2);
printnum<char>(3);
}
此程序打印:
in int method: 2
in char method: 3
它创建了两个由显式模板参数选择的不同printnum(int)
函数。主要用途是当您想从其他具有printnum<T>(int)
类型参数的模板函数调用T
时。
答案 2 :(得分:0)
在
template<typename>
void printnum(int i) {
std::cout<<"in int method:"<<std::endl;
std::cout<< i<<std::endl;
}
与
相同template<typename T>
void printnum(int i) {
std::cout<<"in int method:"<<std::endl;
std::cout<< i<<std::endl;
}
除了参数未命名。由于参数未以任何方式使用(您无法使用它 - 它没有名称),因此它不会影响任何内容。
模板参数没有名称。就是这样。但该函数仍然是一个模板,因此需要传递一个类型参数。同样的方法可以避免命名函数参数以避免&#34;未使用的参数&#34;警告,你可以在这里做同样的事。
(有时你需要在函数中使用未使用的参数,因为回调函数具有给定的签名,你必须声明一个参数,因为回调签名需要它,但它只是你没有使用它)
答案 3 :(得分:-1)
那是因为被调用的函数是由参数的类型决定的。 2
和3
都是int
类型的(字面值),因此调用第一个“变体”(我无法想到更好的描述)。
如果你做了
printnum<int>('A');
printnum<char>('B');
你会发现在这两种情况下都会调用你函数的第二种形式。
无论如何,您滥用模板。滥用语言功能是质疑该功能价值的一个不好的前奏。
更有效的用法就像是;
template<typename T>
void printnum(T i)
{
std::cout<< i << std::endl;
}
这意味着
printnum(1);
printnum("ABC");
将打印数字1,然后在不同的行上打印字符串ABC。
如果您想为int
变体做一些不同的事情,您可以 - 在前面的模板定义之后 -
template<> printnum<int>(int x)
{
std::cout<<"in int method:"<<std::endl; // different output here
std::cout<< i<<std::endl;
}
将调用printnum(1)
(或printnum()
给出任何其他类型int
的值)。同样,如果你想专门研究其他类型。