普通模板只可以採取固定數量的模板引數。然而,有時候我們希望模板可以接收任意數量的模板引數,這個時候可以採用可變引數模板。對於可變引數模板,其將包含至少乙個模板引數包,模板引數包是可以接收0個或者多個引數的模板引數。相應地,存在函式引數包,意味著這個函式引數可以接收任意數量的引數。
乙個可變引數類模板定義如下:
templateclasstuple
{};
可以用任意數量的型別來例項化tuple:
tuple<>t0;tuple
t1;tuple
t2;//tuple<0> error; 0 is not a type
如果想避免出現用0個模板引數來例項化可變引數模板,可以這樣定義模板:
templateclasstuple
{};
此時在例項化時,必須傳入至少乙個模板引數,否則無法編譯。
同樣地,可以定義接收任意引數的可變引數函式模板:
templatevoidf(types ... args);
cout
<列印可變引數的個數
//一些合法的呼叫
f();f(1
);f(
3.4, "
hello
");
對於類模板來說,可變模板引數包必須是模板引數列表中的最後乙個引數(即模板列表引數中的最後乙個引數必須是可變的)。但是對於函式模板來說,則沒有這個限制,考慮下面的情況:
templateclassinvalid
{};
//這是非法的定義,因為永遠無法推斷出u的型別
template
void valid(u u, ts ... args); //
這是合法的,因為可以推斷出u的型別
//void invalid(ts ... args, u u);
//非法的,永遠無法推斷出u
valid(
1.0, 1, 2, 3); //
此時,u的型別是double,ts是
無法直接遍歷傳給可變引數模板的不同引數,但是可以借助遞迴的方式來使用可變引數模板。可變引數模板允許建立型別安全的可變長度引數列表。下面定義乙個可變引數函式模板processvalues(),它允許以型別安全的方式接受不同型別的可變數目的引數。函式processvalues()會處理可變引數列表中的每個值,對每個引數執行對應版本的handlevalue()。
//處理每個型別的實際函式
void handlevalue(int value)
void handlevalue(double value)
void handlevalue(string value)
//用於終止迭代的基函式
templatevoid
processvalues(t arg)
//可變引數函式模板
templatevoid
processvalues(t arg, ts ... args)
可以看到這個例子用了三次... 運算子,但是有兩層不同的含義。用在引數模板列表以及函式引數列表,其表示的是引數包。前面說到,引數包可以接受任意數量的引數。用在函式實際呼叫中的...運算子,它表示引數包擴充套件,此時會對args解包,展開各個引數,並用逗號分隔。模板總是至少需要乙個引數,通過args...解包可以遞迴呼叫processvalues(),這樣每次呼叫都會至少用到乙個模板引數。對於遞迴來說,需要終止條件,當解包後的引數只有乙個時,呼叫接收乙個引數模板的processvalues()函式,從而終止整個遞迴。
假如對processvalues()進行如下呼叫:
processsvalues(1, 2.5, "test");
其產生的遞迴呼叫如下:
processsvalues(1, 2.5, "test");
handlevalue(1);
processsvalues(
2.5, "
test");
handlevalue(
2.5);
processsvalues(
"test");
handlevalue(
"test
");
#include #include#include
#include
using
namespace
std;
//用來終止遞迴並處理包中最後乙個元素
template void
print(t t)
//包中除了最後乙個元素之外的其他元素都會呼叫這個版本的print
template void
print(t t, types ...arg)
//測試
intmain()
類模板的全特化:就是模板中的引數型別都確定了
類模板的偏特化:就是模板中有些引數確定了,有些沒有確定
注意:模板的全特化和偏特化都要在類模板的基礎上實現
//先定義類模板
templateclass
test
private
: t1 a;
t2 b;
};//
模板的全特化
template<>
class test
private
:
inta;
char
b; };
//模板的偏特化
template class test
private
:
char
a; t2 b;
};intmain()
可變參模板模板模板引數
include include include include include include include include using namespace std namespace nmsp1 classa template typename.args class myclasst 主模板 t...
C 可變參模板
可變引數模板是乙個接受可變數目引數的模板函式或模板類,在模板引數列表中,typename 指出接下來的引數表示0個或多個型別的列表,乙個型別名後面跟省略號表示0個或多個給定型別的非型別引數的列表。在函式引數列表中,如果乙個引數的型別是乙個模板引數包,則此引數也是乙個函式引數包。可變引數模板通常是遞迴...
可變參模板續 模板模板引數
include include include include include using namespace std 從類模板引入 template t u叫模板引數,更具體叫型別模板引數 前面有typename template typename t,型別模板引數 template class ...