日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

C++ 模板的顯式具體化

作者:weixin_45767431 更新時間: 2022-10-29 編程語言

? 本文結合網上的資料對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*代表的是第一個類型參數,還是第二個類型參數。

原文鏈接:https://blog.csdn.net/weixin_45767431/article/details/127577583

欄目分類
最近更新