2015-12-24 38 views
1

我想寫一個將數組的json表示反序列化爲std :: vector的函數。我使用的json庫是Facebook的愚蠢庫的一部分。我想實現像下面出頭,但遺憾的是它不工作:模板函數類型在運行時爲json反序列化轉換

template<typename T> 
static bool deserializeHelper(std::string fieldName, vector<T>& structField, const folly::dynamic& jsonObj) {   
    if(auto* jsonField = jsonObj.get_ptr(fieldName)){ 
     if(jsonField->isArray()) { 
      for(auto& elem : *jsonField) { 
       if(elem.isInt()) { 
        structField.push_back(elem.asInt()); 
       } else if(elem.isString()){ 
        structField.push_back(elem.asString()); 
       } else if(elem.isDouble()) { 
        structField.push_back(elem.asDouble()); 
       } else if(elem.isBool()) { 
        structField.push_back(elem.asBool()); 
       } else return false; 
      } 
     } else return false; 
    } 

    return true; 
} 

在上面的代碼,jsonField是陣列場表示。所以代碼只是試圖循環訪問數組;然後爲每個元素;它會嘗試推回到通用矢量:矢量。問題是代碼無法編譯,因爲它會抱怨它不能從std :: string轉換爲int;當T = int時;

我不知道如何編寫這樣的通用函數,而不需要實現4方法重載函數。 靜態布爾deserializeHelper(的std :: string fieldName的,矢量< int>的& structField,常量愚蠢::動態& jsonObj)....

感謝。

+0

也許使用boost庫的'boost :: variant'類型而不是'std :: vector'可以幫助:http://www.boost.org/doc/libs/1_59_0/doc/html/variant.html –

回答

0

看起來像下面的代碼工作。我只是想知道有沒有什麼瓶頸,開銷,或下面的作品就好了:

template<typename T> 
static bool deserializeHelper(std::string fieldName, vector<T>& structField, const folly::dynamic& jsonObj) { 
    if(auto* jsonField = jsonObj.get_ptr(fieldName)){ 
     if(jsonField->isArray()) { 
      for(auto& elem : *jsonField) { 
       if(elem.isInt()) { 
        int tmp = elem.getInt(); 
        structField.push_back(*(static_cast<T*>(static_cast<void*>(&tmp)))); 
       } else if(elem.isString()){ 
        std::string tmp = elem.getString().toStdString(); 
        structField.push_back(*(static_cast<T*>(static_cast<void*>(&tmp)))); 
       } else if(elem.isDouble()) { 
        double tmp = elem.getDouble(); 
        structField.push_back(*(static_cast<T*>(static_cast<void*>(&tmp)))); 
       } else if(elem.isBool()) { 
        bool tmp = elem.getBool(); 
        structField.push_back(*(static_cast<T*>(static_cast<void*>(&tmp)))); 
       } else return false; 
      } 
     } else return false; 
    } 

    return true; 
} 

基本上,它會嘗試轉換爲void *首先從虛空做一套鑄造前*到T *。我想知道是否有什麼可以改進。

謝謝。

0

兩個類型安全的方式來做到這一點是:

  • 寫4種方法,你已被拒絕;
  • if聲明中測試T

這可能是這個樣子:

#include <type_traits> 

template<typename T> 
static bool deserializeHelper(std::string fieldName, vector<T>& structField, const folly::dynamic& jsonObj) {   
    if(auto* jsonField = jsonObj.get_ptr(fieldName)){ 
     if(jsonField->isArray()) { 
      for(auto& elem : *jsonField) { 
       if(std::is_same<T, bool>::value) { 
        structField.push_back(elem.asBool()); 
       } else if(std::is_convertible<int64_t, T>::value) { 
        structField.push_back(elem.asInt()); 
       } else if(std::is_convertible<std::string, T>::value){ 
        structField.push_back(elem.asString()); 
       } else if(std::is_convertible<double, T>::value) { 
        structField.push_back(elem.asDouble()); 
       } else return false; 
      } 
     } else return false; 
    } 
    return true; 
} 

所有這些if S的將這樣的編譯後的代碼是彷彿只有用支在那裏爲有效靜態評估。