何為泛型程式設計呢?簡單的說就是,我們按照特定語法寫**,然後讓編譯器去具體實現這些**。而函式模板,就是讓編譯器按照呼叫時的實參自動生成相應的函式版本.
格式如下:
template
returntype functionname(argument-list)
其中template和typename是關鍵字。
tips:
在c++98之前c++是使用class關鍵字來定義模板的,而在c++98開始使用typename關鍵字定義模板了。
示例:現在假設我們想寫乙個swap函式來交換兩個數的值
#include
#include
#include"test_h.h"
using
std::string ;
using
std::cout;
using
std::endl;
//function declaration
template
void swap(t& a,t& b);
int main(int argc, char** argv)
編譯器會根據swap()中的引數型別自動生成int和double版本的函式。
node:
記住template在定義和宣告中都是不能少的
假設有如下模板
template
void f(t a,t b)
如果a,b是陣列的話a=b
是不可以的
如果a,b是結構的話a>b
也是不可以的
所以模板程式設計有時候你要考慮一下引數的特殊性。這時候我們就要用到顯示具體化了
格式如下:
template <>returntyoe function
< type>(type, type)
其中template <>為關鍵字,如果編譯器可以根據引數列表推斷模板型別那麼< type>中的type為可選項
示例:
void swap(int a,int b);
template
<>void swap<>(double, double);
template
void swap(t, t);
上賣弄三種分別為非模板函式,模板的顯式具體化,模板函式
如果程式中同時定義了三種函式,會優先呼叫非模板函式,然後模板的顯式具體化,最後模板函式
一開始定義的模板函式swap(t a,t b)它會告訴編譯器生成函式的方式,但是還沒有生成函式,而當呼叫swap(i1,i2)和swap(d1,d2)時就會生成相應的模板例項。模板的顯式具體化也一樣都是不會生成函式例項的,而是出現了具體型別之後再讓編譯器按照模板具體化建立函式例項。
在以前c++只能通過判斷函式引數來例項化函式,這種叫做隱式例項化而現在的c++可以通過顯式例項化了,格式如下
template returntype function
(type,type);
上面的**告訴編譯器建立乙個接受type型別函式的例項,其中template為關鍵字,必須要寫的。
示例:
template
void swap(int,int);//函式例項化
template
<> void swap(int,int);//模板具體化
上面的例項化告訴編譯器使用swap模板生成乙個接受int引數的函式例項,他已經在**中了。
而模板顯式具體化,告訴編譯器當呼叫函式時如果引數為int時,就按照模板具體化定義的形式建立函式。
除了上面的顯示例項化的手段,我們還可以在程式中手動使用函式模板來建立顯示例項化,如下
template
void swap(t a,t b)
……int i=19;
double d=19.0;
cout
(i,d)當同時有非模板函式,模板函式,模板顯示具體化時定義時。會優先呼叫非模板函式,然後模板的顯示具體化,最後模板函式
void f(int); //#1
float f(float,float=3); //#2
void f(char) //#3
char * f(const
char *) //#4
char f(const chat *) //#5
template
void f(const t &) //#6
template
void ft *) //#7
如果呼叫
f('b')
上面#3,#5,#6都是原型匹配,但是#3,#5優先於#6,#6優先於#1
template
void f(t a,t b)
所以c++11引入了關鍵字decltype來解決這個問題
int x;
decltype(x) y;//y is int
decltype(x+y) xy;//xy is x+y type
xy=x+y;
decltype(x+y)xy=x+y;//xy is x+y type
上面是三種decltype的簡單使用。而對於如下標準格式
decltype(expression) var;
編譯器會編譯乙個核對表,核對表的簡化版如下
第一步:如果expresssion是乙個沒有用括號的識別符號,則var的型別與該識別符號相同,包括const等修飾符
double x=19.0;
double y=19.0
double &rx=x;
const
double *pd;
decltype (x) w;//w is double
decltype (rx) u;
//u is double &
decltype (pd) v ;
//v const double *
第二步:如果experssion是乙個函式呼叫,var是的型別與函式返回值一樣
int f(int);
decltype( f(3)) m//m is int
note:
這實際不會呼叫函式,編譯器會根據函式原型判斷返回值型別
第三步:如果expression是乙個左值,則var為指向型別的引用。這好像意味著前面w應為引用型別,因為x是乙個左值,但是這種情況下已經在第一步處理過了。要進入第三步expression不能是未用括號括起來的識別符號
double xx=19.0;
decltype((xx))r2=xx;//r2 is double &
devltype(xx)w=xx//w is double
第四步:如果前面條件都不滿足,則var的型別與expression型別相同
int j=3;
int& k=j;
int& n=j;
decltype(j+6) i1;//i1 is int
decltype(100l) i2;
//i2 is long
decltype(k+n) i3;
//i3 is int
templatetype f(t a,t b)
decltype (a+b) 不行嗎?因為這時候還沒有定義a,b,編譯器不知道a,b是什麼。c++11為auto新增了語法功能來解決這個問題,如下
auto f(int i1,int i2)->double;
auto告訴編譯器返回型別在後面寫著。他可以和decltype 連用
auto f(int i1,int i2)->decltype(x+y);
這樣就完成了返回型別的自動換了。
c 函式模板
include using namespace std template t max t a,t b,t c int main int main int i1 185,i2 76,i3 567,i double d1 56.63,d2 90.23,d3 3214.78,d long g1 67854...
c 函式模板
關鍵字template總是放在模板的電腦關於與宣告的最前面,關鍵字後面是用逗號分隔的模板參數列,該列表是模板參數列,不能為空。模板引數可以是乙個模板型別引數,它代表了一種型別 也可以是乙個模板非型別引數,它代表了乙個常量表示式。模板型別引數由關鍵字class或typename後加乙個識別符號構成。在...
C 函式模板
c 提供了函式模板 function template 所謂函式模板,實際上是建立乙個通用函式,其函式型別和形參型別不具體指定,用乙個虛擬的型別來代表。這個通用函式就稱為函式模板。凡是函式體相同的函式都可以用這個模板來代替,不必定義多個函式,只需在模板中定義一次即可。在呼叫函式時系統會根據實參的型別...