C++新經典模板與泛型編程:用成員函數重載實現std::is_convertible

用成員函數重載實現is_convertible

C++標準庫中提供的可變參類模板std::is_convertible,這個類模板的主要能力是判斷能否從某個類型隱式地轉換到另一個類型,返回的是一個布爾值true或false。例如,一般的從int轉換成float或從float轉換成int,都是可以的。又如,有一個類A和一個類B,代碼如下。

class A
{
};class B : public A
{
};

因為類B的父類是類A,所以從類B轉換到類A是可以的,但從類A轉換到類B是不行的。
在main()主函數中加入幾行測試代碼:

#include "killCmake.h"#include<string>using namespace std;class A
{
};class B : public A
{
};int main()
{// std::is_convertible<X,Y> :是判斷能否從X類型轉到Y類型std::cout << std::is_convertible<float, int>::value << std::endl;std::cout << std::is_convertible<int, float>::value << std::endl;// 子類轉換到父類可以,但是父類不能轉換到子類,會截斷std::cout << std::is_convertible<A, B>::value << std::endl;std::cout << std::is_convertible<B, A>::value << std::endl;return 0;
}

在這里插入圖片描述
從結果中可以看到,從類A轉換到類B是不允許的(結果為0),其他幾個轉換都是可以的(結果為1)。
在明白了std::is_convertible的功能后,現在就來深入了解一下它的實現源碼。這里,IsConvertibleHelper類模板和一個IsConvertible類模板,完成與std::is_convertible同樣的功能。這里尤其注意,不要把類型模板的參數搞反,第1個類型模板參數叫作FROM,第2個類型模板參數叫作TO。IsConvertibleHelper類模板實現的功能是測試從FROM類型轉換到TO類型是否可行。

template<typename From,typename To>
struct IsConvertibleHelper
{
private:static void testfunc(To);template<typename = decltype(testfunc(std::decltype<From>()))>static std::true_type test(void*);static std::false_type test(...);
public:using type = decltype(test(nullptr));
};
  • 上面的代碼與以往講過的IsDefConstructibleHelper代碼非常類似,重載的test()成員函數返回類型分別是std::true_type和std::false_type。如果FROM類型能轉換成TO類型,那么就會匹配返回std::true_type的test()成員函數(成員函數模板);否則會匹配返回std::false_type的test成員函數。
  • 值得注意的是,返回std::true_type的test()成員函數中類型模板參數默認值的寫法,看起來是用decltype推斷testfunc()成員函數的返回類型,傳遞給testfunc()的實參可以看作一個FROM類型的對象(std::declval()),如果FROM類型能被順利地轉換為TO類型,那么通過decltype推斷testfunc()的返回類型的寫法就是有效的(SFINAE原則),test()函數就會返回std::true_type,否則編輯器就會匹配返回類型為std::false_type的test()成員函數。
  • 現在,繼續實現IsConvertible類模板,讓其繼承剛剛定義的IsConvertibleHelper模板中的type(type是一個類型,為std::true_type或std::false_type),代碼如下。
#include "killCmake.h"#include<string>using namespace std;class A
{
};class B : public A
{
};template<typename From,typename To>
struct IsConvertibleHelper
{
private:static void testfunc(To);template<typename = decltype(testfunc(std::decltype<From>()))>static std::true_type test(void*);static std::false_type test(...);
public:using type = decltype(test(nullptr));
};template<typename From,typename To>
struct IsConvertible : IsConvertibleHelper<From, To>::type // struct 默認的繼承方式是public繼承
{
};int main()
{// std::is_convertible<X,Y> :是判斷能否從X類型轉到Y類型std::cout << std::is_convertible<float, int>::value << std::endl;std::cout << std::is_convertible<int, float>::value << std::endl;// 子類轉換到父類可以,但是父類不能轉換到子類,會截斷std::cout << std::is_convertible<A, B>::value << std::endl;std::cout << std::is_convertible<B, A>::value << std::endl;return 0;
}

在這里插入圖片描述

  • 當FROM類型能夠轉換成TO類型時,IsConvertible的父類(IsConvertibleHelper<FROM, TO>::type)相當于std::true_type類型;當FROM類型不能轉換成TO類型時,IsConvertible的父類就相當于std::false_type類型。此時,std::true_type或std::false_type類型中的靜態成員變量value的值為true(1)或false(0)就代表FROM類型能否轉換為TO類型。

可以用一個變量模板簡化書寫:

#include "killCmake.h"#include<string>using namespace std;class A
{
};class B : public A
{
};template<typename From,typename To>
struct IsConvertibleHelper
{
private:static void testfunc(To);template<typename = decltype(testfunc(std::decltype<From>()))>static std::true_type test(void*);static std::false_type test(...);
public:using type = decltype(test(nullptr));
};template<typename From,typename To>
struct IsConvertible : IsConvertibleHelper<From, To>::type // struct 默認的繼承方式是public繼承
{
};template<typename From,typename To>
constexpr bool IsConvertible_v = IsConvertible<From, To>::value;int main()
{std::cout << IsConvertible_v<float, int> << std::endl;std::cout << IsConvertible_v<int, float> << std::endl;std::cout << IsConvertible_v<A, B> << std::endl;std::cout << IsConvertible_v<B, A> << std::endl;return 0;
}

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/206963.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/206963.shtml
英文地址,請注明出處:http://en.pswp.cn/news/206963.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

使用Plex結合cpolar搭建本地私人媒體站并實現遠程訪問

文章目錄 1.前言2. Plex網站搭建2.1 Plex下載和安裝2.2 Plex網頁測試2.3 cpolar的安裝和注冊 3. 本地網頁發布3.1 Cpolar云端設置3.2 Cpolar本地設置 4. 公網訪問測試5. 結語 1.前言 用手機或者平板電腦看視頻&#xff0c;已經算是生活中稀松平常的場景了&#xff0c;特別是各…

劇本殺小程序搭建:打造線上劇本殺新體驗

劇本殺是一款以角色扮演為主的游戲&#xff0c;一度成為了年輕人的最喜愛的社交游戲。在劇本殺市場需求下&#xff0c;劇本殺規模也迅速上升。今年第一季度&#xff0c;劇本殺市場規模環比增長47%&#xff0c;市場整體消費水平逐漸呈上升趨勢。 隨著劇本殺的不斷發展&#xff…

echarts繪制一個環形圖2

其他echarts&#xff1a; echarts繪制一個環形圖 echarts繪制一個柱狀圖&#xff0c;柱狀折線圖 echarts繪制一個餅圖 效果&#xff1a; 組件代碼&#xff1a; <template><div class"wrapper"><div ref"doughnutChart2" id"dough…

ORACLE數據庫實驗總集 實驗六 SQL 語句應用

一、 實驗目的 &#xff08;1&#xff09; 掌握數據的插入&#xff08;INSERT&#xff09;、 修改&#xff08;UPDATE&#xff09; 和刪除&#xff08;DELETE&#xff09; 操作。 &#xff08;2&#xff09; 掌握不同類型的數據查詢&#xff08;SELECT&#xff09; 操作。 二、…

阿里滴滴之后,騰訊視頻也崩了!網友追問:下一個是誰?

繼滴滴“崩了”一夜后&#xff0c;剛過去不到一周時間&#xff0c;互聯網“崩了”連續劇又迎來了續集。 就在剛剛&#xff0c;也是晚間時分&#xff0c;網友曝出騰訊視頻崩了&#xff0c;不能追劇了。接著&#xff0c;騰訊視頻官方便現身回應&#xff0c;坐實了傳聞。 還是同…

JVM虛擬機:如何查看JVM初始和最終的參數?

本文重點 在前面的課程中&#xff0c;我們學習了如何查看當前程序所處于的xx參數&#xff0c;本文再介紹一種如何參看JVM的xx參數&#xff1f; 查看JVM的所有初始化參數 方式一&#xff1a;java -XX:PrintFlagsInitial 方式二&#xff1a;java -XX:PrintFlagsInitial -versio…

【自學篇】Python篇-第一天溫度轉換

1、規則 輸入 華氏度 轉換為 攝氏度 輸入 攝氏度 轉換為 華氏度 轉換公式&#xff1a; 華氏度 攝氏度 * 1.8 32 攝氏度 &#xff08;華氏度32 &#xff09;/1.8 2、python代碼 TempStr input() if TempStr[-1] in [F,f]:print("轉換后的溫度值&#xff1a;{:.2f}C&…

淺談Elasticsearch備份和恢復

Elasticsearch 備份和恢復功能 Elasticsearch 是一個分布式搜索和分析引擎&#xff0c;廣泛應用于各種場景&#xff0c;如日志分析、全文搜索和實時數據處理。在使用 Elasticsearch 時&#xff0c;數據的安全和可用性至關重要。本文將詳細講解 Elasticsearch 的備份和恢復功能…

Uncle Maker: (Time)Stamping Out The Competition in Ethereum

目錄 筆記后續的研究方向摘要引言貢獻攻擊的簡要概述 Uncle Maker: (Time)Stamping Out The Competition in Ethereum CCS 2023 筆記 本文對以太坊 1 的共識機制進行了攻擊&#xff0c;該機制允許礦工獲得比誠實同行更高的挖礦獎勵。這種名為“Uncle Maker”的攻擊操縱區塊時間…

mysql數據庫中int字段長度,即int(1)和int(10)的區別

1.起因 為什么想起來看這個問題&#xff0c;是最近有同事問mysql的init類型的字段長度的問題&#xff0c;他問int(1)和int(10)是什么意思&#xff0c;是字段長度越大&#xff0c;能存儲的數字越大么&#xff1f;咋一問&#xff0c;還有點懵&#xff0c;從慣性思維來看&#xf…

React 中虛擬DOM是什么,為什么需要它?

注意&#xff1a;本節主要講React中的虛擬DOM&#xff0c;但是虛擬DOM并不是React中特有的內容。 1. React 中虛擬 DOM是什么&#xff1f; 虛擬DOM是對真實DOM的描述&#xff0c;虛擬DOM是JS對象&#xff0c;實際上就是 JSX 通過 babel 轉換成 React.createElement()&#xff…

8.3 C++11對Unicode的支持

一、C11對Unicode的支持 在C98中&#xff0c;引入wchar_t對Unicode支持&#xff0c;但是后來由于不同平臺下wchar_t的寬度并不相同(8,16,32位)&#xff0c;導致可移植性受到影響。因此從C11開始引入了char16_t、char32_t以及原有的char&#xff0c;分別存儲utf16&#xff0c;u…

邊緣端部署的典型目標識別網絡

邊緣端&#xff08;Edge&#xff09;部署深度學習目標檢測網絡通常涉及到在資源受限的設備上執行模型推斷。這里有一些邊緣端部署深度學習目標檢測網絡的常見策略和技術&#xff1a; 輕量化模型&#xff1a; 選擇或設計輕量級的深度學習模型&#xff0c;例如MobileNet、Squeez…

來自OpenAI的官方解釋:ChatGPT中的GPTs與Assistants API的區別是什么?有什么差異?

本文原文來自DataLearnerAI的官方網站&#xff1a; 來自OpenAI的官方解釋&#xff1a;ChatGPT中的GPTs與Assistants API的區別是什么&#xff1f;有什么差異&#xff1f; | 數據學習者官方網站(Datalearner)https://www.datalearner.com/blog/1051701996595465 OpenAI發布的產…

圖解算法數據結構-LeetBook-查找01_第一個只出現一次的字符

某套連招動作記作僅由小寫字母組成的序列 arr&#xff0c;其中 arr[i] 第 i 個招式的名字。請返回第一個只出現一次的招式名稱&#xff0c;如不存在請返回空格。 示例 1&#xff1a; 輸入&#xff1a;arr “abbccdeff” 輸出&#xff1a;‘a’ 示例 2&#xff1a; 輸入&…

3D Web輕量引擎HOOPS Communicator如何實現對大模型的渲染支持?

除了讀取輕松外&#xff0c;HOOPS Communicator對超大模型的支持效果也非常好&#xff0c;它可以支持30GB的包含70萬個零件和3.5億個三角面的Catia裝配模型&#xff01; 那么它是如何來實現對大模型的支持呢&#xff1f; 我們將從以下幾個方面與大家分享&#xff1a;最低幀率…

python核心階段(五)—— 面向對象三大特性

1.封裝 概念&#xff1a;封裝主要是指將一些屬性和相關方法封裝在一個對象中&#xff0c;對外隱藏內部具體實現細節 作用&#xff1a;1&#xff09;使用起來更加方便&#xff0c;類似于提供了一個工具箱 2&#xff09;保證數據的安全&#xff08;設置私有屬性&#xff09; 3&am…

高精度加法,減法,乘法,除法(下)(C語言)

前言 上一篇博客我們分享了高精度加法&#xff0c;減法,這一期我將為大家講解高精度乘法和高精度除法。那讓我們開始吧&#xff01; 對加法和減法感興趣的話就點我 文章目錄 1&#xff0c;乘法2&#xff0c;除法3&#xff0c;尾聲 1&#xff0c;乘法 讓我們想想我們平時做數學…

openpyxl讀取Excel文件忽略單元格公式僅讀取所顯示的值

目錄 前言解決方案先不加&#xff1a;看讀取信息加上參數&#xff1a;看讀取信息完整代碼 前言 我們在讀取Excel文件時&#xff0c;假如某行或者某列是利用公式生成的&#xff0c;但是我們在利用openpyxl進行讀取時&#xff0c;發現讀取到的是公式&#xff0c;而非顯示的值 解…

Java并行和并發有什么區別?

Java并行和并發有什么區別&#xff1f; 并行和并發是兩個在多線程編程中經常使用的概念&#xff0c;它們描述了不同的多任務處理方式。 并發&#xff08;Concurrency&#xff09;&#xff1a; 定義&#xff1a;并發是指多個任務共享資源&#xff0c;但是并不一定同時執行。它強…