国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > C++ > 正文

關(guān)于C++ variant 類型問(wèn)題

2019-11-08 01:50:31
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友
一直想知道C++標(biāo)準(zhǔn)庫(kù)有沒(méi)有類似Qt下QVariant功能的類。整理了下網(wǎng)上關(guān)于這部分的說(shuō)法:1. std::variant 的實(shí)現(xiàn)是 C++17的, 使用需要考慮編譯器的支持2. _variant_t 這個(gè)在 comutil.h 文件內(nèi),  應(yīng)該主要是windows 下的解決方案.。.3.boost variant 和 boost any  麻煩的是需要引用boost庫(kù). 4. 在了就是自己編寫(xiě),或者把boost等其他第三方庫(kù)中關(guān)于這部分的分離出來(lái)單獨(dú)使用參考:http://bbs.csdn.net/topics/392042283           http://www.jb51.net/article/42985.htm       以下為別人寫(xiě)的一個(gè)實(shí)現(xiàn)variant類似于union,它能代表定義的多種類型,允許將不同類型的值賦給它。它的具體類型是在初始化賦值時(shí)確定

boost中的variant的基本用法:

復(fù)制代碼代碼如下:typedef variant<int,char, double> vt;vt v = 1;v = '2';v = 12.32;

  用variant一個(gè)好處是可以擦除類型,不同類型的值都統(tǒng)一成一個(gè)variant,雖然這個(gè)variant只能存放已定義的類型,但這在很多時(shí)候已經(jīng)夠用了。 取值的時(shí)候,通過(guò)get<T>(v)來(lái)獲取真實(shí)值。然而,當(dāng)T類型與v的類型不匹配時(shí),會(huì)拋出一個(gè)bad_cast的異常來(lái)。boost的variant拋出的異常往往沒(méi)有更多的信息,不知道到底是哪個(gè)類型轉(zhuǎn)換失敗,導(dǎo)致發(fā)生異常調(diào)試時(shí)很不方便。因此,就考慮用c++11去實(shí)現(xiàn)一個(gè)vairiant, 這個(gè)variant可以很容易知道取值時(shí),是什么類型轉(zhuǎn)換失敗了。

打造variant需要解決的問(wèn)題:第一,要在內(nèi)部定義一個(gè)char緩沖區(qū)。

  緩沖區(qū)用來(lái)存放variant的值,這個(gè)值是variant定義的多種類型中的某種類型的值,因此,這個(gè)緩沖區(qū)要足夠大,能夠存放類型最大(sizeof(Type))的值才可以,這個(gè)緩沖區(qū)的大小還必須在編譯期計(jì)算出來(lái)。因此需要首先要解決的是variant值存放的緩沖區(qū)定義的問(wèn)題。

第二,要解決賦值的問(wèn)題。

  將值賦給vairiant時(shí),需要將該值的類型ID記錄下來(lái),以便在后面根據(jù)類型取值。將值保存到內(nèi)部緩沖區(qū)時(shí),還需要用palcement new在緩沖區(qū)創(chuàng)建對(duì)象。另外,還要解決一個(gè)問(wèn)題,就是賦值時(shí)需要檢查variant中已定義的類型中是否含有該類型,如果沒(méi)有則編譯不通過(guò),以保證賦值是合法的。

第三,要解決取值的問(wèn)題。

  通過(guò)類型取值時(shí),要判斷類型是否匹配,如果不匹配,將詳情打印出來(lái),方便調(diào)試。

打造variant的關(guān)鍵技術(shù):

1.找出最大的typesize第一個(gè)問(wèn)題中需要解決的問(wèn)題是如何找出多種類型中,size最大的那個(gè)類型的size。看看如何從多種類型中找出最大類型的size。

復(fù)制代碼代碼如下:template<typename T, typename... Args>struct MaxType : std::integral_constant<int,(sizeof(T)>MaxType<Args...>::value ? sizeof(T) : MaxType<Args...>::value) >

{};

template<typename T>struct MaxType<T> : std::integral_constant<int, sizeof(T) >{};

通過(guò)這個(gè)MaxType就可以在編譯期獲取類型中最大的maxsize了:MaxType<Types...>::value。

2.類型檢查和緩沖區(qū)中創(chuàng)建對(duì)象第二個(gè)問(wèn)題中需要解決兩個(gè)問(wèn)題,1.檢查賦值的類型是否在已定義的類型中;2.在緩沖區(qū)中創(chuàng)建對(duì)象及析構(gòu);

先看看如何判斷類型列表中是否含有某種類型:

復(fù)制代碼代碼如下:template < typename T, typename... List >struct Contains : std::true_type {};

template < typename T, typename Head, typename... Rest >struct Contains<T, Head, Rest...>    : std::conditional< std::is_same<T, Head>::value, std::true_type,

Contains<T, Rest...>>::type{};

template < typename T >struct Contains<T> : std::false_type{};

通過(guò)bool值Contains<T, Types>::vaule就可以判斷是否含有某種類型。

再看看如何在緩沖區(qū)中創(chuàng)建對(duì)象。

通過(guò)placement new在該緩沖區(qū)上創(chuàng)建對(duì)象,new(data) T(value);其中data表示一個(gè)char緩沖區(qū),T表示某種類型。在緩沖區(qū)上創(chuàng)建的對(duì)象還必須通過(guò)~T去析構(gòu),因此還需要一個(gè)析構(gòu)vairiant的幫助類:

復(fù)制代碼代碼如下:template<typename... Args>struct VariantHelper;

template<typename T, typename... Args>struct VariantHelper<T, Args...> {inline static void Destroy(type_index id, void * data){if (id == type_index(typeid(T)))((T*) (data))->~T();elseVariantHelper<Args...>::Destroy(id, data);}};

template<> struct VariantHelper<>  {inline static void Destroy(type_index id, void * data) { }};

通過(guò)VariantHelper::Destroy函數(shù)就可以析構(gòu)variant了。

3.取值問(wèn)題第三個(gè)問(wèn)題中需要解決取值問(wèn)題,如果發(fā)生異常,就打印出詳細(xì)信息。這個(gè)就比較簡(jiǎn)單了,看后面的實(shí)現(xiàn)代碼就行了。

c++11中完整的variant是如何實(shí)現(xiàn)的:

復(fù)制代碼代碼如下:#include <typeindex>#include <iostream>#include <type_traits>using namespace std;

template<typename T, typename... Args>struct MaxType : std::integral_constant<int,(sizeof(T)>MaxType<Args...>::value ? sizeof(T) : MaxType<Args...>::value) >

{};

template<typename T>struct MaxType<T> : std::integral_constant<int, sizeof(T) >{};

template < typename T, typename... List >struct Contains : std::true_type {};

template < typename T, typename Head, typename... Rest >struct Contains<T, Head, Rest...>: std::conditional< std::is_same<T, Head>::value, std::true_type, Contains<T,

Rest...>>::type{};

template < typename T >struct Contains<T> : std::false_type{};

template<typename... Args>struct VariantHelper;

template<typename T, typename... Args>struct VariantHelper<T, Args...> {inline static void Destroy(type_index id, void * data){if (id == type_index(typeid(T)))((T*) (data))->~T();elseVariantHelper<Args...>::Destroy(id, data);}};

template<> struct VariantHelper<>  {inline static void Destroy(type_index id, void * data) { }};

template<typename... Types>class Variant{typedef VariantHelper<Types...> Helper_t;public:

Variant(void) :m_typeIndex(typeid(void)){}

~Variant(){Helper_t::Destroy(m_typeIndex, &m_data);}

template<typename T>bool Is(){return (m_typeIndex == type_index(typeid(T)));}

template<typename T>T& Get(){if (!Is<T>()){cout << typeid(T).name() << " is not defined. " << "current type is " <<

m_typeIndex.name() << endl;throw std::bad_cast();}

return *(T*) (&m_data);}

    template <class T,     class = typename std::enable_if<Contains<typename

std::remove_reference<T>::type, Types...>::value>::type>    Variant(T&& value) : m_typeIndex(type_index(typeid(T)))    {        Helper_t::Destroy(m_typeIndex, &m_data);        typedef typename std::remove_reference<T>::type U;        new(m_data) U(std::forward<T>(value));    }

PRivate:char m_data[MaxType<Types...>::value];std::type_index m_typeIndex;};

測(cè)試代碼:

復(fù)制代碼代碼如下:void TestVariant(){    typedef Variant<int, char, double> cv;    int x = 10;

    cv v =x;    v = 1;    v = 1.123;    v = "";//compile error    v.Get<int>(); //1    v.Get<double>(); //1.23    v.Get<short>(); //exception: short is not defined. current type is

int.    v.Is<int>();//true}

總結(jié):c++11實(shí)現(xiàn)的variant在用法上和boost.variant保持一致,但實(shí)現(xiàn)更簡(jiǎn)潔,50行代碼搞定。而且還能在拋出異常時(shí)提示詳細(xì)信息,方便調(diào)試。

c++11 boost技術(shù)交流群:296561497,歡迎大家來(lái)交流技術(shù)。


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表

圖片精選

主站蜘蛛池模板: 图木舒克市| 聂拉木县| 温州市| 广德县| 高台县| 武定县| 金昌市| 泸水县| 汶川县| 娱乐| 永福县| 河间市| 丽江市| 开化县| 宁南县| 镇赉县| 潮州市| 长葛市| 滕州市| 郸城县| 阳东县| 新乐市| 疏附县| 莱西市| 盘山县| 库尔勒市| 洛南县| 梁山县| 买车| 中西区| 阿勒泰市| 侯马市| 孝感市| 绵阳市| 顺义区| 巴中市| 普陀区| 太仓市| 隆尧县| 南澳县| 福海县|