2017-02-19 56 views
-2

的说我有这样的代码:使用模板<typename>

#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-callprintnum()函数的char-variant(事实并非如此)。

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

+0

其用途是用一个模板参数定义一个模板:一个类。就是这样。 “2”和“3”都是“int”,因此采用“int”参数的函数被选中。模板参数不是一个因素。 –

+0

肯定有“使用”。 C++库中有许多模板将一个类作为参数。 –

+0

嗯,是的,但这并没有回答 – FloriHe

回答

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)功能。主要用途是当您想从某个具有T类型参数的其他模板函数调用printnum<T>(int)时。

+0

谢谢,那正是我所寻找的,这是有道理的。 – FloriHe

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

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

+0

谢谢,这是一个很好的解释。所以通常唯一的影响是创建一个函数族,在编译时选择一个函数族,这与家族所有其他函数相同。但我不明白为什么这是有道理的。 – FloriHe

+0

它通常不会。目前还不清楚为什么要创建一个函数模板,而不是使用它的模板参数。 –

-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"); 

将打印,随后在不同的行的字符串ABC数字1。

如果你想做一些对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) 。同样,如果你想专门为其他类型。

+0

是的,我完全理解这一点。该示例没有被选择显示出好的代码。它被选为这个问题的中介:模板有什么用? – FloriHe

+0

问题是,通过这样做,你迫使人们解释你使用的代码有什么问题。而且,由于代码质量差,你会得到像我所给出的例子一样的使用示例....展示了如何执行你对代码给出的期望。 – Peter

+0

无论如何,这个问题“模板”的用法是什么?“结构太笼统 - 太多可能的答案与您用来介绍问题的例子无关。所以我已经投票决定在这个基础上结束这个问题。 – Peter

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; 
} 

不同之处在于,所述参数是未命名。由于参数没有以任何方式使用(你不能使用它 - 它没有名字),它不影响任何东西。

模板参数没有名称。而已。但是该函数仍然是一个模板,所以需要将它传递给一个类型参数。与避免命名函数参数以避免“未使用的参数”警告相同,您可以在此处执行相同的操作。

(有时你必须未使用的功能参数,因为回调有一个给定的签名,因为回调签名要求它必须声明一个参数,但它只是碰巧你不使用它)

+0

因此,这个构造是无用的。否则,你可以举一个例子,为什么这个构造不是无用的。 – FloriHe

+0

@FloriHe避免命名模板参数与避免命名函数参数一样有用:避免“未使用参数”警告。 – milleniumbug