亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

關于C++ variant 類型問題

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

boost中的variant的基本用法:

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

  用variant一個好處是可以擦除類型,不同類型的值都統一成一個variant,雖然這個variant只能存放已定義的類型,但這在很多時候已經夠用了。 取值的時候,通過get<T>(v)來獲取真實值。然而,當T類型與v的類型不匹配時,會拋出一個bad_cast的異常來。boost的variant拋出的異常往往沒有更多的信息,不知道到底是哪個類型轉換失敗,導致發生異常調試時很不方便。因此,就考慮用c++11去實現一個vairiant, 這個variant可以很容易知道取值時,是什么類型轉換失敗了。

打造variant需要解決的問題:第一,要在內部定義一個char緩沖區。

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

第二,要解決賦值的問題。

  將值賦給vairiant時,需要將該值的類型ID記錄下來,以便在后面根據類型取值。將值保存到內部緩沖區時,還需要用palcement new在緩沖區創建對象。另外,還要解決一個問題,就是賦值時需要檢查variant中已定義的類型中是否含有該類型,如果沒有則編譯不通過,以保證賦值是合法的。

第三,要解決取值的問題。

  通過類型取值時,要判斷類型是否匹配,如果不匹配,將詳情打印出來,方便調試。

打造variant的關鍵技術:

1.找出最大的typesize第一個問題中需要解決的問題是如何找出多種類型中,size最大的那個類型的size??纯慈绾螐亩喾N類型中找出最大類型的size。

復制代碼代碼如下: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) >{};

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

2.類型檢查和緩沖區中創建對象第二個問題中需要解決兩個問題,1.檢查賦值的類型是否在已定義的類型中;2.在緩沖區中創建對象及析構;

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

復制代碼代碼如下: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{};

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

再看看如何在緩沖區中創建對象。

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

復制代碼代碼如下: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) { }};

通過VariantHelper::Destroy函數就可以析構variant了。

3.取值問題第三個問題中需要解決取值問題,如果發生異常,就打印出詳細信息。這個就比較簡單了,看后面的實現代碼就行了。

c++11中完整的variant是如何實現的:

復制代碼代碼如下:#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;};

測試代碼:

復制代碼代碼如下: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}

總結:c++11實現的variant在用法上和boost.variant保持一致,但實現更簡潔,50行代碼搞定。而且還能在拋出異常時提示詳細信息,方便調試。

c++11 boost技術交流群:296561497,歡迎大家來交流技術。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲成人激情在线观看| 国产精品自产拍在线观看中文| 欧美国产日韩一区二区| 国产一区二区三区丝袜| 精品香蕉一区二区三区| 亚洲视频在线观看视频| 久久久久久有精品国产| 另类美女黄大片| 欧洲成人免费aa| 欧美激情视频在线| 欧美亚洲一区在线| 亚洲国模精品一区| 欧美激情奇米色| 亚洲国产精品久久久久| 一区二区三区回区在观看免费视频| 亚洲精品资源美女情侣酒店| 国产噜噜噜噜久久久久久久久| 国产日韩欧美成人| 亚洲精品久久久久久久久| 国产日韩欧美中文| 久久久极品av| 欧美中文字幕在线| 亚洲系列中文字幕| 久久97精品久久久久久久不卡| 国产欧亚日韩视频| 成人免费看黄网站| 国产精品久久网| 国产精品免费观看在线| 久久中文字幕视频| 亚洲性猛交xxxxwww| 中文字幕九色91在线| 亚洲国产婷婷香蕉久久久久久| 成人网页在线免费观看| 欧美国产日韩一区| 91热精品视频| 国产精品免费福利| 欧美精品www| 一区二区三区四区在线观看视频| 在线视频欧美日韩精品| 亚洲精品自拍第一页| 精品国产精品自拍| 久久成人综合视频| 久久精品中文字幕一区| 亚洲国产成人精品久久久国产成人一区| 国产69精品久久久久久| 综合久久五月天| 国产aaa精品| 中国日韩欧美久久久久久久久| 91精品国产综合久久香蕉922| 色综合久综合久久综合久鬼88| 自拍亚洲一区欧美另类| 亚洲女人天堂色在线7777| 97视频在线观看视频免费视频| 黑人精品xxx一区一二区| 97在线视频免费| 91久久久国产精品| xxxxx成人.com| 亚洲xxxxx| 国产男人精品视频| www.亚洲免费视频| 爽爽爽爽爽爽爽成人免费观看| 美女视频黄免费的亚洲男人天堂| 国产精品专区第二| 九九视频这里只有精品| 正在播放国产一区| 韩国三级电影久久久久久| 欧美麻豆久久久久久中文| 欧美日韩综合视频网址| 久久激情视频免费观看| 久久九九热免费视频| 日韩视频免费大全中文字幕| 日韩欧美黄色动漫| 青青草原成人在线视频| 538国产精品一区二区在线| 亚洲美女精品成人在线视频| 国产在线观看一区二区三区| 亚洲视频在线免费观看| 欧美激情第三页| 欧美激情伊人电影| 亚洲欧洲成视频免费观看| 久久久久中文字幕2018| 亚洲国产天堂网精品网站| 亚洲欧美日韩精品久久| 亚洲成人动漫在线播放| 欧美精品18videosex性欧美| 在线视频欧美日韩| 欧美亚洲国产日韩2020| 国产69精品99久久久久久宅男| 日韩最新中文字幕电影免费看| 91po在线观看91精品国产性色| 98精品国产高清在线xxxx天堂| 久久精品国产免费观看| 成人黄色短视频在线观看| 欧美一级大片在线免费观看| 国产久一一精品| 亚洲欧美日韩中文在线| 91欧美日韩一区| 欧美中文在线字幕| 国产欧美一区二区三区久久| 欧美日韩中文字幕在线视频| 91香蕉国产在线观看| 久久婷婷国产麻豆91天堂| 2019国产精品自在线拍国产不卡| 欧美亚洲视频一区二区| 亚洲精品国产免费| 亚洲综合在线中文字幕| 最近2019中文字幕一页二页| 亚洲精品美女久久久久| 亚洲美女av在线| 国产亚洲精品美女久久久| 日韩中文在线不卡| 91精品国产综合久久香蕉| 欧美在线观看网址综合| 日韩在线观看网址| 欧美成人激情视频| 国产亚洲a∨片在线观看| 欧美性猛交xxxx富婆| 国产日韩专区在线| 国产成人精品av在线| 国产精品视频久久久| 久久精品视频亚洲| 亚洲黄色av网站| 亚洲国产成人久久| 久久精品色欧美aⅴ一区二区| 久久69精品久久久久久久电影好| 日本久久中文字幕| 亚洲精品一区二区三区婷婷月| 97**国产露脸精品国产| 日韩在线免费视频| 狠狠躁夜夜躁久久躁别揉| 91精品成人久久| 国产精品十八以下禁看| 国产一区二区三区在线观看网站| 久久在线观看视频| 91香蕉嫩草影院入口| 在线观看亚洲视频| 日韩中文字幕在线| 成人激情在线观看| 欧美大尺度电影在线观看| 亚洲欧美日韩一区二区在线| 在线视频欧美日韩| 精品亚洲永久免费精品| 中文字幕国内精品| 亚洲精品av在线| 97久久精品在线| 亚洲色图美腿丝袜| 亚洲国产日韩欧美在线99| 97人人做人人爱| 欧美做爰性生交视频| 久久久视频免费观看| 国产福利精品在线| 97视频在线观看亚洲| 欧美性开放视频| 久久久久久久电影一区| 亚洲成人av片在线观看| 中文字幕欧美国内| 欧美三级免费观看| 精品亚洲一区二区三区四区五区| 欧美影院成年免费版| 日韩美女av在线免费观看| 日韩av在线网址| 欧美日韩视频免费播放| 色综合久久88色综合天天看泰| 日韩欧美主播在线|