[討論] boost::variant有沒有更好的做法?

看板C_and_CPP作者 (殺人貓™)時間6年前 (2017/09/05 16:40), 編輯推噓1(1020)
留言21則, 4人參與, 最新討論串1/2 (看更多)
算半個作業文吧 (?) 不過是寫專案的時候碰到的問題 我們有一組Data Access Layer,之前為了讓他能方便吃下所有型態 所以Value的部分用boost::variant,如下這樣 typedef boost::variant<std::string, int, char*> ValueType; ValueType get(const std::string&& key); void set(const std::string&& key, ValueType value); 然後把它們存在一組map裡面 std::map<std::string, ValueType> map; 當然使用上並沒有想像中那麼方便啦,這是後話(尤其是get,真的是歐麥尬) 不過看起來也算能用就是了 對於boost::variant使用比較熟的同學應該就知道他能吃三個值了 (本例來講就是std::string, int, char*) 但是在做serialization的時候,發現boost::serialization對這種case簡直無解 std::stringstream ss; boost::archive::text_oarchive ar(ss); ar << map; std::cout << ss.str() << std::endl; 會跑出一大組壯觀的錯誤,當然,身為專業的C++碼農,本來就不期待boost無痛搞好 所以就開始自己認命的寫serialization了 void SimpleDevDBSpace::serialize(const std::string&& folder) { for(auto i : map) { //Use reference to improve performance const std::string& name = i.first; ValueType& value = i.second; switch(value.which()) { 當然這對大多數人來講都已經good enough了,但是我總覺得心裡癢癢的 value.watch()傳回來的是order,也就是0 = string, 1 = int, 2 = char* 但是這不夠泛用,如果今天把variant型別改成<int, std::string, float, long> 這樣的話還要記得去改value.which的case handle,這顯然是有點問題的 所以我的需求是,有沒有什麼方法可以讓std::string, int, char* 成為一個array 讓我需要增加支援type時,改一個地方即可,有點像這樣 TypeArray ARR = {std::string, int, char*}; typedef boost::variant<{ARR}> ValueType; 而且這個可以被輪詢 我知道value還額外一個提供value.type(),不過我想不出他對我的需求有什麼用 他用了一個很類似loki的Type2Int的方法,但是我找不到公開方法可以去轉 有人可以給我一點建議嗎?雖然我覺得這需求已經有點龜毛了..... -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 60.250.140.192 ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1504600853.A.FC2.html

09/05 16:49, , 1F
any?
09/05 16:49, 1F

09/05 16:57, , 2F
any無法限制型別,client愛塞啥就塞啥,會對應到死...
09/05 16:57, 2F

09/05 17:02, , 3F
就是因為要明確定義支援type 所以才用variant的
09/05 17:02, 3F

09/05 17:05, , 4F
用visitor不能嗎?
09/05 17:05, 4F

09/05 17:06, , 5F
variant是有原生支援visitor沒錯啦... 恩我研究看看
09/05 17:06, 5F

09/05 17:07, , 6F
反正都要有個地方針對type去handle serialize就是了
09/05 17:07, 6F

09/05 17:07, , 7F
這樣的話看能不能印得出「缺某種type的serializer」
09/05 17:07, 7F

09/05 17:07, , 8F
的錯誤來提醒使用者...
09/05 17:07, 8F

09/05 17:09, , 9F
不過visitor是可以試試 只是寫法可能會比較不值觀
09/05 17:09, 9F

09/05 17:09, , 10F
附帶一提 boost::serialization::variant.hpp是用
09/05 17:09, 10F

09/05 17:09, , 11F
visitor沒錯 只是針對map的話...搞不好可以直接用
09/05 17:09, 11F

09/05 17:10, , 12F
只要自己處理map的部分就好(抓頭)
09/05 17:10, 12F

09/05 17:49, , 14F
應該大概類似這樣吧
09/05 17:49, 14F

09/05 17:49, , 15F
感謝 讓我試試看 //bow
09/05 17:49, 15F

09/05 17:53, , 17F
btw, 原來C++17把variant收到std了啊...
09/05 17:53, 17F

09/05 17:53, , 18F
如果要針對不同type handle的話 使用C++17黑魔法
09/05 17:53, 18F

09/05 17:54, , 19F
any, optional, variant 都進 C++17 了
09/05 17:54, 19F

09/05 17:59, , 20F
真是個好消息 我看看project能不能支援 XD
09/05 17:59, 20F

09/06 02:53, , 21F
像 idris 的 HVect 一樣嗎?
09/06 02:53, 21F
文章代碼(AID): #1PhcCL_2 (C_and_CPP)
文章代碼(AID): #1PhcCL_2 (C_and_CPP)