亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C++超詳細(xì)分析type_traits

 更新時(shí)間:2022年08月15日 14:33:36   作者:fl2011sx  
C++的type_traits是一套純粹編譯期的邏輯,可以進(jìn)行一些類型判斷、分支選擇等,主要用于模板編程。使用type_traits并不難,但是我們希望能夠更加深入了解其實(shí)現(xiàn)方式,與此同時(shí),可以更進(jìn)一步體驗(yàn)C++的模板編程

本篇文章旨在引導(dǎo)大家自行實(shí)現(xiàn)type_traits的基礎(chǔ)代碼。

模板編程不像常規(guī)的代碼,可以有if-else這些流控制語(yǔ)句,我們需要充分利用模板、模板特例、類型轉(zhuǎn)換等特性來(lái)實(shí)現(xiàn)編譯期的一系列判斷和類型轉(zhuǎn)換。

定義基礎(chǔ)常量

第一步,我們需要定義true和false兩個(gè)常量,所有的type_traits都基于此。我們的目的就是要用一個(gè)模板類型來(lái)表示是非,其中的value正好是這兩個(gè)值。之后我們更高級(jí)的判斷類型都是繼承自這兩個(gè)類型的其中一個(gè),通過(guò)這種方式獲取value值就可以獲取true和false了。

如果聽這個(gè)解釋有點(diǎn)暈的話,不要緊,我們直接來(lái)看代碼。這里需要注意的是,既然type_traits都是編譯期行為,因此其成員只能是靜態(tài)不可變成員(編譯期就可以確定的成員)。

struct true_type {
    static constexpr bool value = true;
};
struct false_type {
    static constexpr bool value = false;
};

基礎(chǔ)類型判斷

有了基礎(chǔ)常量,我們可以先做一些簡(jiǎn)單的類型判斷,比如說(shuō)判斷這個(gè)類型是不是void。這里的思路是,針對(duì)于所有類型的模板,繼承自false_type,而針對(duì)于void類型,我們給予一個(gè)模板特例,讓他繼承自true_type。這樣一來(lái),只有當(dāng)類型是void的時(shí)候才會(huì)推導(dǎo)true,其他的就會(huì)推導(dǎo)false。請(qǐng)看例程:

template <typename>
struct is_void : false_type {};
template <>
struct is_void<void> : true_type {};

這里我們可以做一些簡(jiǎn)單的測(cè)試,來(lái)判斷函數(shù)的返回值是否為void:

void test1();
int test2();
int main(int argc, const char *argv[]) {
    std::cout << is_void<decltype(test1())>::value << std::endl; // 1
    std::cout << is_void<decltype(test2())>::value << std::endl; // 0
    return 0;
}

有了判斷void的思路基礎(chǔ),不難寫出判斷其他類型的,比如說(shuō)判斷是否為浮點(diǎn)數(shù),那么只需要對(duì)float,double,long double進(jìn)行特殊處理即可,請(qǐng)看代碼:

template <typename>
struct is_floating_point : false_type {};
template <>
struct is_floating_point<float> : true_type {};
template <>
struct is_floating_point<double> : true_type {};
template <>
struct is_floating_point<long double> : true_type {};

整型判斷相對(duì)復(fù)雜一點(diǎn),需要對(duì)char,signed char,unsigned char,short,unsigned short,int,unsigned,long,unsigned long,long long,unsigned long long都進(jìn)行特例編寫,方法相同,不再贅述。

類型處理

在上一節(jié)編寫is_floating_point的時(shí)候可能會(huì)發(fā)現(xiàn)這樣的問(wèn)題:

int main(int argc, const char *argv[]) {
    std::cout << is_floating_point<const double>::value << std::endl; // 0
    std::cout << is_floating_point<double &>::value << std::endl; // 0
    return 0;
}

但是照理來(lái)說(shuō),const類型以及引用類型不應(yīng)該影響他浮點(diǎn)數(shù)的本質(zhì),當(dāng)然,我們也可以針對(duì)所有的const以及引用情況都編寫模板特例,但這樣太麻煩了,如果有辦法可以去掉const以及引用這些符號(hào),然后再去判斷的話,就會(huì)減少我們很多工作量。與此同時(shí),這樣的類型處理在實(shí)際編程時(shí)也是很有用的。

那么,如何去掉const?請(qǐng)看代碼:

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

同樣的思路,當(dāng)T是const類型時(shí),我們變換成const T,然后只取出T,其他類型時(shí)直接透?jìng)鱐。

同理,用這種方法也可以去除引用:

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

因此,is_floating_point就可以改寫成這樣:

// 基礎(chǔ)判斷降級(jí)為helper
template <typename>
struct is_floating_point_helper : false_type {};
template <>
struct is_floating_point_helper<float> : true_type {};
template <>
struct is_floating_point_helper<double> : true_type {};
template <>
struct is_floating_point_helper<long double> : true_type {};
// remove_reference和remove_const的聲明
template <typename>
struct remove_const;
template <typename>
struct remove_reference;
// 實(shí)際的is_floating_point
template <typename T>
struct is_floating_point : is_floating_point_helper<typename remove_const<typename remove_reference<T>::type>::type> {};

類型選擇

我們搞這樣一系列的類型封裝,最主要的原因是為了在編譯器進(jìn)行邏輯判斷。因此,必然要進(jìn)行一個(gè)選擇邏輯,也就是當(dāng)條件成立時(shí),選擇某一個(gè)類型,不成立時(shí)選擇另一個(gè)類型。這個(gè)功能非常好實(shí)現(xiàn),請(qǐng)看代碼:

template <bool judge, typename T1, typename T2>
struct conditional {
    using type = T1;
};
template <typename T1, typename T2>
struct conditional<false, T1, T2> {
    using type = T2;
};

當(dāng)?shù)谝粋€(gè)參數(shù)為true時(shí),type就與T1相同,否則就與T2相同。

判斷是否相同

我們有時(shí)候還需要判斷兩個(gè)類型是否相同,這部分也很好實(shí)現(xiàn),請(qǐng)看代碼:

template <typename, typename>
struct is_same : false_type {};
template <typename T>
struct is_same<T, T> : true_type {};

tips

其實(shí)按照這些邏輯,我們幾乎可以寫出type_traits中的所有功能了。STL中還實(shí)現(xiàn)了合取、析取、取反等操作,只是將邏輯判斷轉(zhuǎn)為了模板形式,這些用起來(lái)更方便,但不是必須的。大家感興趣可以閱讀這部分源碼。

實(shí)現(xiàn)is_base_of

is_base_of用于判斷兩個(gè)類型是否是繼承關(guān)系,在C++中已經(jīng)存在了對(duì)應(yīng)的關(guān)鍵字用于判斷:

struct B {};
struct D : B {};
struct A {};
int main(int argc, const char *argv[]) {
    std::cout << __is_base_of(B, D) << std::endl; // 1
    std::cout << __is_base_of(B, A) << std::endl; // 0
    return 0;
}

__is_base_of關(guān)鍵字就可以完成這樣的工作,所以我們封裝它為模板即可:

template <typename B, typename D>
struct is_base_of : conditional<__is_base_of(B, D), true_type, false_type> {};

但除了這種直接使用編譯器提供的關(guān)鍵字外,這個(gè)功能還有一種其他的實(shí)現(xiàn)方法。

如何判斷一個(gè)類是否為一個(gè)類的父類呢?其實(shí)就看指針能否轉(zhuǎn)換(多態(tài))即可。請(qǐng)看代碼:

template <typename B, typename D>
true_type test_is_base(B *);
template <typename B, typename D>
false_type test_is_base(void *);
template <typename B, typename D>
struct is_base_of : decltype(test_is_base<B, D>(static_cast<D *>(nullptr))) {};

如果D是B的子類,那么就會(huì)調(diào)用第一個(gè)函數(shù),從而推斷出返回值是true_type,否則調(diào)用第二個(gè)函數(shù),推斷出返回值是false_type。

不過(guò)這樣做還必須加一個(gè)判斷,就是B和D必須都是類才行,而且需要去掉const等因素,詳細(xì)代碼讀者可以自行嘗試,不再贅述。

到此這篇關(guān)于C++超詳細(xì)分析type_traits的文章就介紹到這了,更多相關(guān)C++ type_traits內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Qt之簡(jiǎn)單的異步操作實(shí)現(xiàn)方法

    Qt之簡(jiǎn)單的異步操作實(shí)現(xiàn)方法

    這篇文章主要介紹了Qt之簡(jiǎn)單的異步操作實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • C語(yǔ)言字符串?dāng)?shù)組詳解

    C語(yǔ)言字符串?dāng)?shù)組詳解

    這篇文章主要介紹了C語(yǔ)言字符串?dāng)?shù)組詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • C語(yǔ)言折半查找法的由來(lái)及使用詳解

    C語(yǔ)言折半查找法的由來(lái)及使用詳解

    折半查找法也叫做?分查找,顧名思義就是把數(shù)據(jù)分成兩半,再判斷所查找的key在哪?半中,再重復(fù)上述步驟知道找到?標(biāo)key,下面這篇文章主要給大家介紹了關(guān)于C語(yǔ)言折半查找法的相關(guān)資料,需要的朋友可以參考下
    2022-08-08
  • 一篇文章帶你了解C語(yǔ)言函數(shù)的可重入性

    一篇文章帶你了解C語(yǔ)言函數(shù)的可重入性

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言函數(shù)的可重入性,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • C++ 設(shè)置透明背景圖片

    C++ 設(shè)置透明背景圖片

    這篇文章主要介紹了C++ 設(shè)置透明背景圖片的相關(guān)資料,需要的朋友可以參考下
    2015-06-06
  • VSCode C/C++多文件編譯配置小結(jié)

    VSCode C/C++多文件編譯配置小結(jié)

    本文主要介紹了VSCode C/C++多文件編譯配置小結(jié),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-08-08
  • C++指針與引用的區(qū)別案例詳解

    C++指針與引用的區(qū)別案例詳解

    這篇文章主要介紹了C++指針與引用的區(qū)別案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • 詳解C++編程中對(duì)于函數(shù)的基本使用

    詳解C++編程中對(duì)于函數(shù)的基本使用

    這篇文章主要介紹了詳解C++編程中對(duì)于函數(shù)的使用,包括函數(shù)的參數(shù)和返回值以及調(diào)用等基本的知識(shí)點(diǎn),需要的朋友可以參考下
    2015-09-09
  • C++實(shí)現(xiàn)十進(jìn)制數(shù)轉(zhuǎn)換為二進(jìn)制數(shù)的數(shù)學(xué)算法

    C++實(shí)現(xiàn)十進(jìn)制數(shù)轉(zhuǎn)換為二進(jìn)制數(shù)的數(shù)學(xué)算法

    這篇文章和大家分享一下我個(gè)人對(duì)十進(jìn)制數(shù)轉(zhuǎn)換為二進(jìn)制數(shù)的想法,目前暫時(shí)更新只整數(shù)十進(jìn)制的轉(zhuǎn)換,后續(xù)會(huì)更新帶有小數(shù)的進(jìn)制轉(zhuǎn)換,代碼使用c++實(shí)現(xiàn)
    2021-09-09
  • 一文帶你學(xué)習(xí)C++析構(gòu)函數(shù)

    一文帶你學(xué)習(xí)C++析構(gòu)函數(shù)

    在C++中,析構(gòu)函數(shù)是一種特殊類型的成員函數(shù),用于在對(duì)象生命周期結(jié)束時(shí)被自動(dòng)調(diào)用,本文我們將介紹C++析構(gòu)函數(shù)的一些重要知識(shí)點(diǎn),并提供相應(yīng)代碼示例,需要的朋友可以參考下
    2023-05-05

最新評(píng)論