C++ 模板的显式具体化
? 本文結合網上的資料對C++模板的顯式具體化做了一個總結。
? 對于模板,模板中的語句(函數體或者類)不一定能適應所有的類型,可能會有個別的類型沒有意義,或者會導致語法錯誤。我們希望模板能夠針對某種具體的類型使用不同的算法,可以使用顯式具體化。
函數模板的顯式具體化
typedef struct{string name;int age;float score; } STU; //函數模板 template<class T> const T& Max(const T& a, const T& b); //函數模板的顯示具體化(針對STU類型的顯示具體化) template<> const STU& Max<STU>(const STU& a, const STU& b);template<class T> const T& Max(const T& a, const T& b){return a > b ? a : b; } template<> const STU& Max<STU>(const STU& a, const STU& b){return a.score > b.score ? a : b; }? ? Max<STU>中的STU表明了要將類型參數T具體化為STU類型,原來使用T的位置都應該使用STU替換,包括返回值類型、形參類型、局部變量的類型。Max只有一個類型參數T,并且已經被具體化為STU了,這樣整個模板就不再有類型參數了,類型參數列表也就為空了,所以模板頭應該寫作template<>。另外,Max<STU>中的STU是可選的,因為函數的形參已經表明,這是 STU 類型的一個具體化,編譯器能夠逆推出 T 的具體類型。簡寫后的函數聲明為:
template<> const STU& Max(const STU& a, const STU& b);
??在調用函數時,顯示具體化優先于常規模板,而非模板函數優先于顯示具體化和常規模板。
類模板的顯式具體化
?如果一個可以輸出不同類型坐標的類模板,希望當 x 和 y 都是字符串時以|為分隔,是數字或者其中一個是數字時才以逗號,為分隔,可以使用顯示具體化技術對字符串類型的坐標做特殊處理。
//類模板 template<class T1, class T2> class Point{ public:Point(T1 x, T2 y): m_x(x), m_y(y){ } public:T1 getX() const{ return m_x; }void setX(T1 x){ m_x = x; }T2 getY() const{ return m_y; }void setY(T2 y){ m_y = y; }void display() const; private:T1 m_x;T2 m_y; }; template<class T1, class T2> //這里要帶上模板頭 void Point<T1, T2>::display() const{cout<<"x="<<m_x<<", y="<<m_y<<endl; } //類模板的顯示具體化(針對字符串類型的顯示具體化) template<> class Point<char*, char*>{ public:Point(char *x, char *y): m_x(x), m_y(y){ } public:char *getX() const{ return m_x; }void setX(char *x){ m_x = x; }char *getY() const{ return m_y; }void setY(char *y){ m_y = y; }void display() const; private:char *m_x; //x坐標char *m_y; //y坐標 }; //這里不能帶模板頭template<> void Point<char*, char*>::display() const{cout<<"x="<<m_x<<" | y="<<m_y<<endl; } int main(){( new Point<int, int>(10, 20) ) -> display();( new Point<int, char*>(10, "東京180度") ) -> display();( new Point<char*, char*>("東京180度", "北緯210度") ) -> display();return 0; }運行結果:
x=10, y=20
x=10, y=東京180度
x=東京180度 | y=北緯210度
??Point<char*, char*>表明了要將類型參數 T1、T2 都具體化為char*類型,原來使用 T1、T2 的位置都應該使用char*替換。Point 類有兩個類型參數 T1、T2,并且都已經被具體化了,所以整個類模板就不再有類型參數了,模板頭應該寫作template<>。當在類的外部定義成員函數時,普通類模板的成員函數前面要帶上模板頭,而具體化的類模板的成員函數前面不能帶模板頭。
部分顯式具體化
??C++ 還允許只為一部分類型參數提供實參,這稱為部分顯式具體化。部分顯式具體化只能用于類模板,不能用于函數模板。
??仍然以 Point 為例,假設我現在希望“只要橫坐標 x 是字符串類型”就以|來分隔輸出結果,而不管縱坐標 y 是什么類型,這種要求就可以使用部分顯式具體化技術來滿足:
//類模板 template<class T1, class T2> class Point{ public:Point(T1 x, T2 y): m_x(x), m_y(y){ } public:T1 getX() const{ return m_x; }void setX(T1 x){ m_x = x; }T2 getY() const{ return m_y; }void setY(T2 y){ m_y = y; }void display() const; private:T1 m_x;T2 m_y; }; template<class T1, class T2> //這里需要帶上模板頭 void Point<T1, T2>::display() const{cout<<"x="<<m_x<<", y="<<m_y<<endl; } //類模板的部分顯示具體化 template<typename T2> class Point<char*, T2>{ public:Point(char *x, T2 y): m_x(x), m_y(y){ } public:char *getX() const{ return m_x; }void setX(char *x){ m_x = x; }T2 getY() const{ return m_y; }void setY(T2 y){ m_y = y; }void display() const; private:char *m_x; //x坐標T2 m_y; //y坐標 }; template<typename T2> //這里需要帶上模板頭 void Point<char*, T2>::display() const{cout<<"x="<<m_x<<" | y="<<m_y<<endl; } int main(){( new Point<int, int>(10, 20) ) -> display();( new Point<char*, int>("東京180度", 10) ) -> display();( new Point<char*, char*>("東京180度", "北緯210度") ) -> display();return 0; }運行結果:
x=10, y=20
x=東京180度 | y=10
x=東京180度 | y=北緯210度
? 模板頭template<typename T2>中聲明的是沒有被具體化的類型參數;類名Point<char*, T2>列出了所有類型參數,包括未被具體化的和已經被具體化的。類名后面之所以要列出所有的類型參數,是為了讓編譯器確認“到底是第幾個類型參數被具體化了”,如果寫作template<typename T2> class Point<char*>,編譯器就不知道char*代表的是第一個類型參數,還是第二個類型參數。
總結
以上是生活随笔為你收集整理的C++ 模板的显式具体化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HTML5开发笔记(1)开发常见的7个框
- 下一篇: GDAL坐标转换——TransformP