91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C++中元編程語言怎么用

發布時間:2021-10-21 13:33:45 來源:億速云 閱讀:143 作者:小新 欄目:開發技術

這篇文章將為大家詳細講解有關C++中元編程語言怎么用,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

模板

由于模板元編程需要以面向對象為基礎,所以如有疑問之處可以先補充一點C++面向對象的知識:

C++面向對象這一篇就夠了

泛型初步

由于C++是靜態強類型語言,所以變量一經創建,則類型不得更改。如果我們希望創建一種應用廣泛地復數類型,那么相應地需要基于intfloatdouble這些基礎類型逐一創建,十分麻煩。泛型編程便是為了簡化這一過程而生。

能夠容納不同數據類型作為成員的類被成為模板類,其基本方法為在類聲明的上面加上一行模板聲明代碼

template<typename T>,下一行為class myClass,其調用過程為myClass<T> m。

列舉案例如下

#include<iostream>
using namespace std;
template<typename C>
struct Abstract{
    C real;         //real為C類型
    C im;
    Abstract(C inReal, C inIm){
        real = inReal;
        im = inIm;
    }
    void printVal(){
        cout<<"Abstract:"<<real<<"+"<<im<<"i"<<endl;
    };
    Abstract& multi(Abstract val){
        C temp = real*val.real - im*val.im;
        im = real*val.real + im*val.im;
        real = temp;
        return *this;
    };
};
int main(){
    Abstract<float> fTemp{1,2};//C類型為float
    fTemp.multi(fTemp);
    fTemp.printVal();
    system("pause");
    return 0;
}

函數模板

當然,上述multi并不能實現兩個不同類型的Abstract之間的相乘,所以可以將multi函數改為

template<typename T>
    Abstract<C>& multi(Abstract<T> val){
        C temp = real*val.real - im*val.im;
        im = real*val.real + im*val.im;
        real = temp;
        return *this;
    }

這樣就能夠實現如下功能。

int main(){
    Abstract<float> fTemp{1,2};
    Abstract<int> iTemp{1,2};
    fTemp.multi(iTemp);
    fTemp.printVal();
    getReal(fTemp);
    system("pause");
    return 0;
}

友元

模板類具備一部分普通類的性質,比如struct和class的區別,public、protected、private的性質,以及友元等。模板的聲明特性也可以應用在函數中,例如

#include<iostream>
using namespace std;
template<typename C>
class Abstract{
    C real;
    C im;
public:
    Abstract(C inReal, C inIm){
        real = inReal;
        im = inIm;
    }
    void printVal(){
        cout<<"Abstract:"<<real<<"+"<<im<<"i"<<endl;
    };
    Abstract& multi(Abstract val){
        C temp = real*val.real - im*val.im;
        im = real*val.real + im*val.im;
        real = temp;
        return *this;
    }
    template<typename T> friend void getReal(Abstract<T> num);  //聲明友元
};
template<typename C>
void getReal(Abstract<C> num){
    cout<<num.real<<endl;
}
int main(){
    Abstract<float> fTemp{1,2};
    fTemp.multi(fTemp);
    fTemp.printVal();
    getReal(fTemp);
    system("pause");
    return 0;
}

需要注意的一點是,在模板類中聲明友元,其前綴<typename T>中的類型標識不得與已有的類型標識重復,否則編譯無法通過。

由于函數模板可以針對不同的數據類型進行求解操作,是對函數或者方法實例的抽象,所以又被稱為算法。

模板參數

如果將模板理解為一種類型聲明的函數,那么模板也應該具備一些函數具備的功能。首先其模板參數中可以包含實際類型參數,例如

template<typename T, int max>
class Test{}

其調用時可以寫為

Test<int,256> pixel;

模板同樣支持默認參數,即可以實現如下形式

template<typename T=int, int max=256>
class Test{}
Test pixle;

除了數據類型、值之外,模板本身也可以作為模板參數,例如下面的形式是合法的。

template<typename T, template<typename> class C>
struct Test{
    C<T>* val;
    Test(C<T>* inVal){
        val = inVal;
    }
};
int main(){
    Abstract<int> fTemp{1,2};
    Test<int,Abstract> test(&fTemp);
    test.val->printVal();
    system("pause");
    return 0;
}

其結果為

PS E:\Code\cpp> g++ .\generic.cpp
PS E:\Code\cpp> .\a.exe
Abstract:1+2i
請按任意鍵繼續. . .

需要注意的一點是,在模板類中定義的模板類,需要進行實例化,否則會出現錯誤,所以在Test中,以指針形式創建了模板類。

類型函數

以數據類型為輸入或輸出的函數即為類型函數,在C語言中,sizeof便是一種類型函數,其輸入為數據類型,輸出為數據類型所需要的內存空間。

在C++11中,using可以實現數據類型賦予的功能,其使用方法與typedef相似

template<typename T>
struct Test{
    using type = T;
}

元編程的基本概念

元編程是泛型編程的一個超集,兩者的本質均是針對不同數據類型的算法,后者則更關注傳入參數的廣泛性。如果將元編程分為四個層次

  • 無計算

  • 運算符連接的運算

  • 編譯時具備選擇等非遞歸計算

  • 編譯時具備遞歸運算

那么泛型編程可以作為第一類元編程,或者說更加關注的是參數的傳入傳出過程,而元編程則更關注不同數據類型的選擇過程。

例如,我們可以實現一個最多包含三個元素的元組Tuple,其思路為,三元元素可以看成是一個二元元組與一個參數的組合;二元元組可以看成是一元元組與參數的組合;一元元組則是一個基本數據類型的變量。在這個元組的實現過程中,除了賦值過程實現泛型之外,也需要判斷當前所實現的元組元素個數,如果其初始化參量為3個時,需要遞歸式地創建變量,直到賦值參數為1個。則其實現如下

class Nil{};
//主模板
template<typename T1=Nil, typename T2=Nil, typename T3=Nil>
struct Tuple : Tuple<T2,T3>{
    T1 x;
    using Base = Tuple<T2,T3>;      //三元元組以二元元組為基礎
    //返回值為Tuple<T2,T3>指針類型的base()函數
    //static_cast將this轉化為Base*類型
    Base* base(){return static_cast<Base*>(this);}
    const Base* base() const {return static_cast<const Base*>(this);}
    //構造函數繼承二元元組,在構造本類中x的同時,構造基類Tuple<T2,T3>
    Tuple(const T1& t1, const T2& t2, const T3& t3)
        :Base{t2,t3},x{t1}{}
};
template<typename T1>
struct Tuple<T1>{
    T1 x;
};
template<typename T1, typename T2>
struct Tuple<T1,T2> : Tuple<T2>{
    T1 x;
    using Base = Tuple<T2>;
    Base* base(){return static_cast<const Base*>(this);}
    const Base* base() const {return static_cast<const Base*>(this);}
    Tuple(const T1& t1,const T2& t2):Base{t2}, x{t1}{}
};
template<typename T1, typename T2, typename T3>
void print_elements(ostream& os, const Tuple<T1,T2,T3>& t){
    os<<t.x<<",";
    print_elements(os,*t.base());
}
template<typename T1, typename T2>
void print_elements(ostream& os, const Tuple<T1,T2>& t){
    os<<t.x<<",";
    print_elements(os,*t.base());
}
template<typename T1>
void print_elements(ostream& os, const Tuple<T1>& t){
    os<<t.x;
}
//運算符重載
template<typename T1, typename T2, typename T3>
ostream& operator<<(ostream& os, const Tuple<T1,T2,T3>& t){
    os<<"{";
    print_elements(os,t);
    os<<"}";
    return os;
}
int main(){
    Tuple<int,double,char> x{1,2.5,'a'};
    cout<<x<<endl;
    system("pause");
    return 0;
}

其輸出結果為

PS E:\Code\cpp> g++ .\generic.cpp
PS E:\Code\cpp> .\a.exe
{1,2.5,a}

可變參數模板

上述實現過程非常繁瑣,而且限制了元組中的元素個數,如果標準庫中用上述的書寫風格,那么標準庫除了這個元組之外也寫不了其他的東西了。好在C++模板提供了可變參數的功能,例如,我們可以先將打印模板函數寫為

//typename... T 代表可變參數
template<typename T1, typename... T>
void print_elements(ostream& os, const Tuple<T1,T...>& t){
    os<<t.x<<",";
    print_elements(os,*t.base());
}
template<typename T1>
void print_elements(ostream& os, const Tuple<T1>& t){
    os<<t.x;
}
template<typename... T>
ostream& operator<<(ostream& os, const Tuple<T...>& t){
    os<<"{";
    print_elements(os,t);
    os<<"}";
    return os;
}

其輸出結果為

PS E:\Code\cpp> g++ .\generic.cpp
PS E:\Code\cpp> .\a.exe
{1,2.5,a}
請按任意鍵繼續. . .

然后將Tuple也做相同的更改

template<typename T1, typename... T>
struct Tuple : Tuple<T...>{
    T1 x;
    using Base = Tuple<T...>;      //N+1元元組以N元元組為基
    Base* base(){return static_cast<Base*>(this);}
    const Base* base() const {return static_cast<const Base*>(this);}
    //注意T&...的書寫格式
    Tuple(const T1& t1, const T&... t):Base{t...},x{t1}{}
};
template<typename T>
struct Tuple<T>{
    T x;
};
/*
    print模板
*/
int main(){
    Tuple<string, double,int,char> tt("hello",1.5,1,'a');
    cout<<tt<<endl;
    system("pause");
    return 0;
}

其輸出結果為

PS E:\Code\cpp> g++ .\generic.cpp
PS E:\Code\cpp> .\a.exe
{hello,1.5,1,a}

關于“C++中元編程語言怎么用”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

c++
AI

绵竹市| 延安市| 治多县| 蓝田县| 尉犁县| 香河县| 浮梁县| 泰顺县| 吴江市| 辽宁省| 金坛市| 连山| 墨竹工卡县| 紫金县| 昌邑市| 南雄市| 黑山县| 和硕县| 宝兴县| 山西省| 湖南省| 镇雄县| 故城县| 双鸭山市| 英德市| 贡嘎县| 舟曲县| SHOW| 洞头县| 都匀市| 龙州县| 雷州市| 花垣县| 凤阳县| 普兰店市| 奉贤区| 沈阳市| 鄂托克旗| 文水县| 仁布县| 辉南县|