縱有疾風起,人生不言棄。本文篇幅較長,如有錯誤請不吝賜教,感謝支持。
一.模板的基礎知識
①為什么有模板?
在C++程序中,聲明變量、函數(shù)、對象等實體時,程序設計者需要指定數(shù)據(jù)類型,讓編譯器在程序運行之前進行類型檢查并分配內存,以提高程序運行的安全性和效率。但是這種強類型的編程方式往往會導致程序設計者為邏輯結構相同而具體數(shù)據(jù)類型不同的對象編寫模式一致的代碼。
??案例:
//交換int數(shù)據(jù)
void SwapInt(int& a,int& b)
{
int temp = a;
a = b;
b = temp;
}
//交換char數(shù)據(jù)
void SwapChar(char& a,char& b)
{
char temp = a;
a = b;
b = temp;
}
問題:如果我要交換double類型數(shù)據(jù),那么還需要些一個double類型數(shù)據(jù)交換的函數(shù),繁瑣,寫的函數(shù)越多,當交換邏輯發(fā)生變化的時候,所有的函數(shù)都需要修改,無形當中增加了代碼的維護難度,如果能把類型作為參數(shù)傳遞進來就好了,傳遞int就是int類型交換,傳遞double類型就是double類型交換。
②初識模板
C++標準提供了模板機制,用于定義數(shù)據(jù)類型不同但邏輯結構相同的數(shù)據(jù)對象的通用行為。在模板中,運算對象的類型不是實際的數(shù)據(jù)類型,而是一種參數(shù)化的類型。帶參數(shù)類型的函數(shù)稱為函數(shù)模板,帶參數(shù)類型的類稱為類模板。
例如上面的案例,我們可以定義函數(shù)Swap(),交換兩個參數(shù),我們可以將類型參數(shù)化,如Swap(T,T),其中,T就是參數(shù)化的類型,在調用Swap()函數(shù)時,可以傳入任意類型的數(shù)據(jù),函數(shù)可以根據(jù)傳入的數(shù)據(jù)推導出T的值是哪種數(shù)據(jù)類型,從而進行相應的操作。這樣程序設計者就可以專注于邏輯代碼的編寫,而不用關心實際具體的數(shù)據(jù)類型。
模板就像生產模具,例如,中秋生產月餅,生產月餅的模具就是模板,在做模具時,只關心做出什么樣式的月餅,而不用關心月餅具體的原料是什么(如水果、五仁、豆沙等)。
程序運行時,模板的參數(shù)由實際參數(shù)的數(shù)據(jù)類型決定,編譯器會根據(jù)實際參數(shù)的數(shù)據(jù)類型生成相應的一段可運行代碼,這個過程稱為模板實例化。函數(shù)模板生成的實例稱為模板函數(shù),類模板生成的實例稱為模板類。
二.函數(shù)模板
函數(shù)模板是函數(shù)的抽象,它與普通函數(shù)相似,唯一的區(qū)別就是函數(shù)參數(shù)的類型是不確定的,函數(shù)參數(shù)的類型只有在調用過程中才被確定。
①函數(shù)模板的定義
C++提供了函數(shù)模板(function template.)所謂函數(shù)模板,實際上是建立一個通用函數(shù),其函數(shù)類型和形參類型不具體制定(泛型),用一個虛擬的類型來代表。這個通用函數(shù)就成為函數(shù)模板。凡是函數(shù)體相同的函數(shù)都可以用這個模板代替,不必定義多個函數(shù),只需在模板中定義一次即可。 在調用函數(shù)時系統(tǒng)會根據(jù)實參的類型來取代模板中的虛擬類型,從而實現(xiàn)不同函數(shù)的功能。
定義函數(shù)模板的語法格式如下所示:
上述語法格式中,template是聲明模板的關鍵字,<>中的參數(shù)稱為模板參數(shù);typename關鍵字用于標識模板參數(shù),可以用class關鍵字代替,class和typename并沒有區(qū)別。
- 模板參數(shù)< >中不能為空,一個函數(shù)模板中可以有多個模板參數(shù),模板參數(shù)和普通函數(shù)參數(shù)相似,只是不確定數(shù)據(jù)類型。
- template下面是定義的函數(shù)模板,函數(shù)模板定義方式與普通函數(shù)定義方式相同只是參數(shù)列表中的數(shù)據(jù)類型要使用<>中的模板參數(shù)名表示 。
②函數(shù)模板的使用
template<class T>//T是模板參數(shù)
void mySwap(T &a,T &b)
{
T tmp = a;
a = b;
b = tmp;
}
//使用函數(shù)模版,和正常調用函數(shù)沒區(qū)別
void test()
{
int a = 10,b = 20;
double c=3.1415,d=9.26;
//1.編譯器會根據(jù)實參來自動推導數(shù)據(jù)類型,并生成相應的函數(shù)
mySwap(a,b);//mySwap中的T會變成int類型
cout << "a=" << a <<"b=" << b << endl;
mySwap(c,d);//mySwap中的T會變成double類型
cout << "c=" << c << "d=" << d << endl;
}
??解釋:
- 第一行指出,要建立一個模板,并將類型命名為T。關鍵字template和class是必需的,也可以使用關鍵字typename代替class.另外,必須使用尖括號<>。類型名可以任意選擇(這里為T)。
- 余下的代碼交換兩個T值的算法。模板并不創(chuàng)建任何函數(shù),而只是告訴編譯器如何定義函數(shù)。需要交換int的函數(shù)時,編譯器將按模板模式創(chuàng)建這樣的函數(shù),并用int代替T。同樣,需要交換double的函數(shù)時,編譯器將按模板模式創(chuàng)建這樣的函數(shù),并用double代替T.
③函數(shù)模板實例化
所謂函數(shù)模板實例化,就是用類型參數(shù)替換函數(shù)模板中的模板參數(shù),生成具體類型的函數(shù)定義。
實例化可分為:
- 隱式實例化
- 顯式實例化
下面分別介紹這兩種實例化方式。
1??隱式實例化
隱式實例化是根據(jù)函數(shù)調用時傳入的參數(shù)的數(shù)據(jù)類型確定模板參數(shù)T的類型,模板參數(shù)的類型是隱式確定的。
例如下例調用mySwap()函數(shù)模板時,傳入的是int類型數(shù)據(jù)a和b,編譯器根據(jù)傳入的實參推演出模板參數(shù)T的類型是int,就會根據(jù)函數(shù)模板將T全部替換成int,實例化出一個int類型的函數(shù),如下所示:
//交換int數(shù)據(jù)
void mySwap(int& a,int& b)
{
int temp = a;
a = b;
b = temp;
}
int main()
{
int a=20,b=30;
mySwap(a,b);
return 0;
}
編譯器生成具體類型函數(shù)的這一過程就稱為實例化,生成的函數(shù)稱為模板函數(shù)。
需要注意的是:
①不能在函數(shù)調用的參數(shù)中指定模板參數(shù)的類型,對函數(shù)模板的調用應使用實參推演。例如,只能進行Swap(2,3)這樣的調用,或者定義整型變量int a=20,b=30,再將變量a、b作為參數(shù),進行Swap(a,b)這樣的調用,編譯器會根據(jù)傳入的實參推演出T為int類型,而不能使用Swap(int,int)方式,直接將類型傳入進行調用。
②函數(shù)模板不會減少可執(zhí)行程序的大小,因為編譯器會根據(jù)調用時的參數(shù)類型進行相應的實例化。
2??顯示實例化
隱式實例化不能為同一個模板參數(shù)指定兩種不同的類型。
例如:
template<class T>//T是模板參數(shù)
void mySwap(T &a,T &b)
{
T tmp = a;
a = b;
b = tmp;
}
//就一個模板參數(shù)T,你隱式的給傳兩個數(shù)據(jù)類型
Swap(10,3.14)//編譯器搞不清楚T是什么數(shù)據(jù)類型,二義性。
//那就讓我們顯示的告訴它
函數(shù)參數(shù)類型不一致,編譯器便會報錯。這就需要顯式實例化解決類型不一致的問題。顯式實例化需要指定函數(shù)模板中的模板參數(shù)的數(shù)據(jù)類型,語法格式如下所示:
< >中是顯式實例化的數(shù)據(jù)類型,即要實例化出一個什么類型的函數(shù)。相當于主動告訴編譯器,我希望你將用我傳的參數(shù)的數(shù)據(jù)類型去將模板參數(shù)顯示轉換為該類型,并按照模版規(guī)定的邏輯生成函數(shù)定義。
<實例化類型>尖括號中實例化類型數(shù)量要與你定義模板時定義模板參數(shù)數(shù)量一致,可以理解用你顯示具體化的數(shù)據(jù)類型去替換你定義模板時模板參數(shù)。
??案例:
template<class T>
void mySwap(T& a, T& b)
{
T tmp = a;
a = b;
b = tmp;
}
template void mySwap<int>(int& a, int& b);//int去替換定義函數(shù)模板時的T
void test()
{
int a = 10,b= 3;
mySwap<int>(a, b);//顯示告訴模板mySwap中的T會變成int類型
cout << "a=" << a << endl;
cout << "b=" << b << endl;
}
??代碼運行結果如下:
④函數(shù)模板的具體化(特化、特例化)
1??模板的局限性及解決方法
假設有如下模板函數(shù):
template<class T>
void func(T a, T b)
{ … }
如果代碼實現(xiàn)時定義了賦值操作 a = b,但是T為數(shù)組,這種假設就不成立了同樣,如果里面的語句為判斷語句 if(a>b),但T如果是結構體,該假設也不成立,另外如果是傳入的數(shù)組,數(shù)組名為地址,因此它比較的是地址,而這也不是我們所希望的操作??傊帉懙哪0搴瘮?shù)很可能無法處理某些類型,另一方面,有時候通用化是有意義的,但C++語法不允許這樣做。為了解決這種問題,可以提供模板的重載,為這些特定的類型提供顯示具體化的模板。
2??函數(shù)模板具體化(特化、特例化)
函數(shù)模板的特點是通用性,可以解決某個方面的普遍性問題,但是這個世界上的事情從來不是絕對的,有普遍的,就有特殊的。
可以提供一個具體化的函數(shù)定義,當編譯器找到與函數(shù)調用匹配的具體化定義時,將使用該定義,不再尋找模板,函數(shù)模板是對函數(shù)體重新定義。
具體化(特例化、特化)的語法:
注意顯示實例化的前綴是template,沒有尖括號<>。
舉例:交換兩個學生類的成員變量。
#include <iostream>
using namespace std;
//函數(shù)模板
template<class T>
void mySwap(T &a,T &b)
{
T tmp = a;
a = b;
b = tmp;
cout<<"調用了mySwap(T &a,T &b)"<<endl;
}
class Student
{
public:
Student(int num):score(num){}
int score;
};
//具體化函數(shù)模板,為Student這一數(shù)據(jù)類型單獨寫一份函數(shù)定義
template <>void mySwap<Student>(Student &a,Student &b)
{
int tmp = a.score;
a.score = b.score;
b.score = tmp;
cout<<"具體化函數(shù)模板:template <>void mySwap<Student>(Student &a,Student &b)調用"<<endl;
}
int main()
{
int a = 10,b = 20;
mySwap(a,b);//調用函數(shù)模板
cout << "a=" << a << "b=" << b << endl;
Student s1(150),s2(90);
mySwap(s1,s2);//調用具體化函數(shù)模板
cout << "s1.score" << s1.score<< "s2.score" << s2.score << endl;
return 0;
}
注意:具體化函數(shù)的返回值、函數(shù)名和形參列表與函數(shù)模板相同。但是對于具體化函數(shù)模板,不管是函數(shù)聲明還是定義中,都是具體的數(shù)據(jù)類型,沒有通用的數(shù)據(jù)類型了。
3??實例化和具體化的相同點
實例化和具體化都是用于生成具體的定義,實例化是編譯器借助你提供的數(shù)據(jù)類型來隱式或顯示替換模板中的模板參數(shù)來實例化出函數(shù)定義,而具體化則是你專門為一個具體的數(shù)據(jù)類型寫函數(shù)定義。
例如:
顯示實例化
template void Swap<int>(int&a,int&b)//顯示具體化
//使用Swap()模板生成int類型的函數(shù)定義
//就是編譯器借助你提供的int去顯示替換模板中的模板參數(shù)
//生成int函數(shù)定義類型。
顯示具體化
template<>void Swap <int>(int&a,int&b)//顯示具體化
//不要使用Swap( )模板來生成函數(shù)定義
//而應使用專門為int類型顯式地定義的函數(shù)定義
⑤普通函數(shù)和函數(shù)模板調用規(guī)則
- ?如果函數(shù)有多個原型,則編譯器在選擇函數(shù)調用時,普通函數(shù)優(yōu)先于模板函數(shù),顯式具體化模板優(yōu)先于函數(shù)模板。
- ?如果希望使用函數(shù)模板,可以用空模板參數(shù)強制使用函數(shù)模板。
- ?如果函數(shù)模板可以產生一個更好的匹配,那么選擇模板。
#include <iostream>
using namespace std;
//普通函數(shù)
void mySwap(int a, int b)
{
int tmp = a;
a = b;
b = tmp;
cout << "調用了普通函數(shù)mySwap(int a,int b)" << endl;
}
//函數(shù)模板
template<class T>
void mySwap(T& a, T& b)
{
T tmp = a;
a = b;
b = tmp;
cout << "調用了函數(shù)模板mySwap(T &a,T &b)" << endl;
}
class Student
{
public:
Student(int num) :score(num) {}
int score;
};
//顯示具體化
template <>void mySwap<Student>(Student& a, Student& b)
{
int tmp = a.score;
a.score = b.score;
b.score = tmp;
cout << "具體化函數(shù)模板:template <>void mySwap<Student>(Student &a,Student &b)調用" << endl;
}
int main()
{
int a = 10, b = 20;
//如果函數(shù)模板和普通函數(shù)都能匹配,c++編譯器優(yōu)先考慮普通函數(shù)
mySwap(a, b);
//如果我必須要調用函數(shù)模板,那么怎么辦?
//可以通過空模板實參列表的語法限定編譯器只能通過模板匹配
mySwap<>(a, b);
cout << "a=" << a << "b=" << b << endl;
Student s1(150), s2(90);
//調用顯示具體化函數(shù)模板
mySwap(s1, s2);
cout << "s1.score:" << s1.score << "s2.score:" << s2.score << endl;
//此時普通函數(shù)和顯示具體化模板都沒有很好的匹配
//所以使用函數(shù)模板可以產生一個更好的匹配,那么選擇模板
char d = 'd', e = 'e';
mySwap(d, e);
return 0;
}
⑥函數(shù)模板的注意事項
1??可以為類的成員函數(shù)創(chuàng)建模板,但不能是虛函數(shù)和析構函數(shù)。
#include <iostream>
#include<string>
using namespace std;
class Maker
{
public:
template<typename T>
Maker(T a)
{
cout<<a<<endl;
}
template<typename T>
void show(T b)
{
cout<<b<<endl;
}
};
int main()
{
Maker m1("感謝支持強風吹拂king的博客");
m1.show(666);
}
上例將Maker的構造函數(shù)和成員函數(shù)show聲明成函數(shù)模板,可以接受任意的數(shù)據(jù)類型。
如果將show聲明為虛函數(shù)會怎么樣呢?
也不能把析構函數(shù)聲明成函數(shù)模板,一個類的析構函數(shù)只有一個,根本沒有參數(shù),不需要模板。
2??只要使用函數(shù)模板,就必須明確數(shù)據(jù)類型(不論是顯示實例化還是隱式實例化),讓編譯器知道模板參數(shù)到底是個什么數(shù)據(jù)類型,確保實參與函數(shù)模板能匹配上,生成具體的函數(shù)定義。
舉例:
template<class T>//T是模板參數(shù)
void mySwap(T &a,T &b)
{
T tmp = a;
a = b;
b = tmp;
}
//使用函數(shù)模版
int main()
{
int a = 10,b = 20;
mySwap(a,b);
cout << "a=" << a << endl;
cout << "b=" << b << endl;
}
現(xiàn)在mySwap函數(shù)描述了一種通用類型T,函數(shù)這兩個形參都是T定義的,也就是說這兩個形參的數(shù)據(jù)類型必須相同,在main函數(shù)中,a和b都是int類型沒有任何問題。
int main()
{
int a = 10
char b = 20;
mySwap(a,b);
cout << "a=" << a << endl;
cout << "b=" << b << endl;
}
如果將b改為字符,編譯器報錯了,模板參數(shù)T不明確,未能找到匹配的重載函數(shù)。
實參與函數(shù)模板的匹配,和函數(shù)重載道理一致,如果匹配不上就會報錯。
把函數(shù)模板的形參都刪掉,函數(shù)里面的代碼也刪掉。現(xiàn)在mySwap函數(shù)沒有參數(shù),那么編譯還能通過嗎?
template<class T>//T是模板參數(shù)
void mySwap()
{
cout<<"show函數(shù)被調用"<<endl;
}
//使用函數(shù)模版
int main()
{
mySwap();
}
未能推導模板參數(shù)。
也就是說模板參數(shù)很死板,一定要明確數(shù)據(jù)類型,上面無參show函數(shù),不能通過參數(shù)隱式實例化函數(shù)模板,那就只能顯示實例化。
mySwap<int>();
3??使用函數(shù)模板時,如果是隱式實例化函數(shù)模板,不會發(fā)生隱式類型轉換,如果顯式實例化函數(shù)模板,則可以發(fā)生隱式類型轉換。
舉例:
template<class T>//T是模板參數(shù)
T Add (T a,T b)
{
return a+b;
}
//使用函數(shù)模版
int main()
{
int a = 10,b = 20;
cout<<Add(a,b)<<endl;
}
現(xiàn)在a和b都是整型,把他們作為函數(shù)模板的實參,編譯器推導出來的就是整型,與函數(shù)模板的定義是匹配的。
我們將b改為字符,在C++中字符是可以隱式轉換成整型的。
int main()
{
int a = 10;
char b = 20;
cout<<Add(a,b)<<endl;
}
模板參數(shù)不明確,看來隱式實例化沒有將字符b轉換成整型。
那我們顯示實例化試一下:
int main()
{
int a = 10;
char b = 'a';
cout<<Add<int>(a,b)<<endl;
}
編譯成功。也就是說如果顯式實例化函數(shù)模板,則可以發(fā)生隱式類型轉換。
4??如果函數(shù)模板有多個模板參數(shù),則每個模板參數(shù)前都必須使用關鍵字class或typename修飾。
例如:
template<typename T, typename U>//兩個關鍵字可以混
void func(T t, U u){}
template<typename T,U>//錯誤,每一個模板參數(shù)前都必須有關鍵字修飾
void func(T t, U u){}
5??全局作用域中聲明的與模板參數(shù)同名的對象、函數(shù)或類型,在函數(shù)模板中將被隱藏。
例如:
int num=9000;
template<typename T>
void func(T t)
{
T num;
cout<<num<<endl;//輸出的是局部變量num,全局int類型的num被屏蔽
}
在函數(shù)體內訪問的num是T類型的變量num,而不是全局int類型的變量num。
6??函數(shù)模板中聲明的對象或類型不能與模板參數(shù)同名。
例如:
template<typename T>
void func(T t) ?
{
typedef float T;//錯誤,定義的類型與模板參數(shù)名相同
?} ??
7??模板參數(shù)名在同一模板參數(shù)列表中只能使用一次,但可在多個函數(shù)模板聲明或定義之間重復使用。
例如:
template<typename T, typename T>//錯誤,在同一個模板中重復定義模板參數(shù) ?
void func1(T x, T y){} ?
template<typename T> ?
void func2(T z){} ?
template<typename T>//在不同函數(shù)模板中可重復使用相同的模板參數(shù)名
?void func3(T w){}??
⑦函數(shù)模板的分文件編寫
函數(shù)模板只是函數(shù)的描述,沒有實體,創(chuàng)建函數(shù)模板的代碼放在頭文件中。
函數(shù)模板的具體化有實體,編譯的原理和普通函數(shù)一樣,所以,聲明放在頭文件中,定義放在源文件中。
例如把下面這段代碼分文件編寫:
#include <iostream>
using namespace std;
void Swap(int a, int b) // 普通函數(shù)。
{
cout << "使用了普通函數(shù)。\n";
}
template <typename T>
void Swap(T a, T b) // 函數(shù)模板。
{
cout << "使用了函數(shù)模板。\n";
}
template <>
void Swap(double a, double b) // 函數(shù)模板的具體化版本。
{
cout << "使用了具體化的函數(shù)模板。\n";
}
int main()
{
Swap(1,2); //將使用普通函數(shù)。
Swap(1.3, 3.5); //將使用具體化的函數(shù)模板。
Swap('c', 'd'); //將使用函數(shù)模板。
}
頭文件public.h,存放函數(shù)的聲明
#pragma once
#include <iostream>
using namespace std;
void Swap(int a, int b); //普通函數(shù)的聲明
template <typename T>
void Swap(T a, T b) // 函數(shù)模板的定義
{
cout << "使用了函數(shù)模板。\n";
}
template <>
void Swap(double a, double b); // 函數(shù)模板的具體化的聲明
public.cpp,存放函數(shù)的實現(xiàn)
#include "public.h"
void Swap(int a, int b) //普通函數(shù)的實現(xiàn)
{
cout << "使用了普通函數(shù)。\n";
}
template <>
void Swap(double a, double b) // 函數(shù)模板的具體化的實現(xiàn)
{
cout << "使用了具體化的函數(shù)模板。\n";
}
demo01.cpp 測試文件
#include "public.h"
int main()
{
Swap(1,2); // 將使用普通函數(shù)。
Swap(1.3, 3.5); // 將使用具體化的函數(shù)模板。
Swap('c', 'd'); // 將使用函數(shù)模板。
}
三.函數(shù)模板高級
①decltype關鍵字
先來看一個示例:
template<typename T1,typename T2>
void func(T1 a, T2 b)
{
//其他代碼
??? tmp=a+b;
//其他代碼
}
func函數(shù)模板描述了兩個通用類型T1和T2,形參a和b分別用T1和T2定義,在函數(shù)體內聲明tmp保存a+b的結果,那么tmp怎么聲明,用什么數(shù)據(jù)類型,T1還是T2,還是其他?
如果T1是double,T2是int,那么最終結果是double類型;如果T1是short,T2是int,那么最終結果是int類型;還有除了C++的內置數(shù)據(jù)類型,結構體和類,還可以重載+號運算符,這樣情況就更復雜了,這樣的話tmp又將定義成什么類型呢?
在C++11中,decltype操作符,用于查詢表達式的數(shù)據(jù)類型。
語法:
decltype(表達式) var;
decltype分析表達式并返回它的類型,
用這個類型定義var變量。
decltype分析表達式并返回它的類型,不會計算執(zhí)行表達式。函數(shù)調用也一種表達式,因此不必擔心在使用decltype時執(zhí)行了函數(shù)。
decltype推導規(guī)則(按步驟):
- 1)如果表達式是一個沒有用括號括起來的標識符,decltype本身自帶的()不算,則var的類型與該標識符的類型相同,包括const等限定符。
int main()
{
const short a = 100;
decltype(a) var=666;
//var的類型將和a保持一致。
//注意:如果decltype分析表達式的類型是引用
//那么必須初始化這個引用
short b = 10;
short& pa = b;
decltype(pa) var2 = b;//var2的類型是short&,初始化var2的引用指向b;、
cout << "var:" << var <<"var2:" << var2 << endl;
}
- 2)如果表達式是一個函數(shù)調用,則var的類型與函數(shù)的返回值類型相同(函數(shù)不能返回void,但可以返回void * ,因為void * 可以聲明變量)。
int func()
{
cout<<"調用了func函數(shù)"<<endl;
return 666;
}
int main()
{
int b=100;
decltype(func()) val=b;
}
大家看,val的類型,是func函數(shù)的返回類型int。
,我們運行代碼,發(fā)現(xiàn)并沒有調用func函數(shù),這也說明decltype不會計算執(zhí)行表達式。
?還有一點:
在decltype中填函數(shù)名和函數(shù)調用是兩回事。
int main()
{
decltype(func()) val=b;
//填函數(shù)調用,得到的是函數(shù)的返回類型
decltype(func) *val2=func;
//只填函數(shù)名得到的是函數(shù)的類型
//再加*號就是函數(shù)指針類型,我們讓val2指向func函數(shù)
val2();//借助函數(shù)指針val2調用func函數(shù)
}
- 3)如果表達式是一個左值(能取地址)(要排除第一種情況)、或者用括號括起來的標識符,那么var的類型是表達式的引用。
int func()
{
cout << "調用了func函數(shù)" << endl;
return 666;
}
int main()
{
short a = 100;
decltype(a) var;
//var的類型將和a保持一致。
decltype((a)) var2=a;//此時的a用括號括起來了,那么var2就是short&類型
decltype((func)) val3 = func;
//如果func不加(),那val3就是函數(shù)類型
//但加了()就是函數(shù)類型的引用
val3();//函數(shù)類型引用也可以調用函數(shù)。
}
文章來源:http://www.zghlxwxcb.cn/news/detail-493984.html
- 4)如果上面的條件都不滿足,則var的類型與表達式的類型相同。
如果需要多次使用decltype,可以結合typedef和using,給數(shù)據(jù)類型起別名。
那么我們現(xiàn)在用decltype關鍵字去解決最初的問題
template<typename T1,typename T2>
void func(T1 a, T2 b)
{
//其他代碼
decltype(a+b) tmp=a+b;
cout<<"tmp="<<tmp<<endl;
//其他代碼
}
int main()
{
func(3.14,600);
}
文章來源地址http://www.zghlxwxcb.cn/news/detail-493984.html
到了這里,關于C++核心編程——詳解函數(shù)模板的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!