1

我想编写一个函数,将数组的 json 表示反序列化为 std::vector。我正在使用的 json 库是 Facebook 的愚蠢库的一部分。我想实现以下目标,但不幸的是它不起作用:

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 个方法重载函数。static bool deserializeHelper(std::string fieldName, vector< int >& structField, const folly::dynamic& jsonObj) ....

谢谢。

4

2 回答 2

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*,然后再从 void* 转换为 T*。我想知道是否有什么可以改进的。

谢谢。

于 2015-12-24T01:52:37.637 回答
0

执行此操作的两种类型安全方法是:

  • 写4个方法,你已经拒绝了;和
  • Tif语句中测试。

这可能看起来像这样:

#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;
}

所有这些ifs 都将被静态评估,因此编译后的代码就像只有 used-branch 一样有效。

于 2017-03-21T11:35:26.923 回答