使用模板<typename>

时间:2017-02-19 02:31:46

标签: c++ c++11 templates

说我的代码如下:

#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-callchar-variant函数的printnum(),这不是情况下。

所以我的一般问题是: template<typename>构造的用途是什么?

4 个答案:

答案 0 :(得分:1)

对于所有类型T,您都有一系列函数,将int作为参数(Tint之间没有关联);顺便说一下,所有人都在做同样的事情。对于所有类型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;
}

Demo

这里有一系列功能。实际上只定义了这个系列的两个成员(尝试使用任何其他实例化会导致链接器错误)。模板参数明确地选择该族的特定成员;因为只有一个可行的函数可以调用,所以不会执行重载决策。

答案 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)

那是因为被调用的函数是由参数的类型决定的。 23都是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的值)。同样,如果你想专门研究其他类型。