我們知道,用模板的時(shí)候可以為他提供兩種類型的模板形參:一種是類型模板形參,一種是非類型模板形參。例如如下聲明:
template<class T>void foo(T t); //用的類型模板形參
template<class T,int n>void foo(T t); //用了類型模板形參,同時(shí)還用到了非類型模板形參int 兩者的區(qū)別是:對(duì)應(yīng)類型模板形參,編譯器會(huì)根據(jù)實(shí)參(對(duì)應(yīng)模板函數(shù))或者用戶指定類型來實(shí)例化對(duì)應(yīng)的模板函數(shù)或類型。而非類型模板形參主要是用來在模板函數(shù)調(diào)用時(shí)指定該形參的值。
非類型模板形參最常用的是用來自動(dòng)獲取數(shù)組的維數(shù)。比如,我們給某個(gè)函數(shù)傳遞一個(gè)數(shù)組,并在函數(shù)內(nèi)部打印這個(gè)數(shù)組的值,如果沒有模板,我們的做法就可能是如下這樣:
void print(int r[],int N)
{
for (int i=0;i<N;++i)
{
cout<<r[i]<<",";
}
cout<<endl;
}
因?yàn)槲覀冃枰罃?shù)組的維數(shù),所以必須要求用戶傳遞第二個(gè)參數(shù)作為維數(shù)傳入。
但是,如果是用非類型模板參數(shù),又該如何用呢?
我們?nèi)绻o出如下的方案,并不能完全達(dá)到我們的目的:
template<class T,int N>
void print(T r[N])
{
for (int i=0;i<N;++i)
{
cout<<r[i]<<",";
}
cout<<endl;
}
因?yàn)槿绻@樣調(diào)用:
int main(){
int ss[] = {1,2,3,4,5,6,7,8,9};
print(ss); //或者print<int>(ss);
return 0;
}
編譯器會(huì)抱怨說:“void print(T [N])”: 未能從“int [9]”為“int [N]”推導(dǎo) 模板 參數(shù)”。也就是我們還是得指定N:print<int,9>(ss)才行。如果是這樣,那豈不還不如將維數(shù)放到函數(shù)的參數(shù)里面了。是不是?
其實(shí),這完全不能怪編譯器或者模板,因?yàn)橹灰@樣寫就完全可以了:
template<class T,int N>
void print(T (&r)[N])
{
for (int i=0;i<N;++i)
{
cout<<r[i]<<",";
}
cout<<endl;
}
我們就可以直接調(diào)用:
print(ss); //或者print<int>(ss);
就可以了。這是為什么呢?
其實(shí)原理是很簡單的,如果我們直接將數(shù)組名傳給一個(gè)函數(shù),數(shù)組將退化為一個(gè)指針,所以編譯器自然也就無法用指針來推導(dǎo)維數(shù)了。但是我們強(qiáng)調(diào)傳的是引用的話,編譯器就明確知道這是一個(gè)數(shù)組,所以就去推導(dǎo)維數(shù)。我們可以給上面的程序加一句打印語句來測(cè)試:
template<class T,int N>
void print(T (&r)[N])


{
cout<<sizeof(r)<<endl;
for (int i=0;i<N;++i)

{
cout<<r[i]<<",";
}
cout<<endl;
}
template<class T,int N>
void print1(T r[N])


{
cout<<sizeof(r)<<endl;
for (int i=0;i<N;++i)

{
cout<<r[i]<<",";
}
cout<<endl;
}
int main()


{

int ss[] =
{1,2,3,4,5,6,7,8,9};
print(ss);
print1<int,9>(ss);

return 0;
} 運(yùn)行結(jié)果如下:
36
1,2,3,4,5,6,7,8,9,
4
1,2,3,4,5,6,7,8,9,
很明顯可以看出,傳引用的方式他知道是一個(gè)數(shù)組,所以sizeof是按數(shù)組的方式計(jì)算的4*9=36.而第二種方式盡管我告訴他維數(shù)了,并且打印出結(jié)果了,但是絲毫沒有改變編譯器將print1的參數(shù)T r[N]視為一個(gè)指針的事實(shí),所以sizeof的值為4.
好了,總結(jié)一下就是:
如果希望用非類型模板形參的方式取數(shù)組的維數(shù)時(shí),請(qǐng)記住用數(shù)組引用的方式作為形參!