Приведение типов шаблонных функций во время выполнения для десериализации json

Я хочу написать функцию, которая десериализует 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& structField, const folly::dynamic& jsonObj) ....

Благодарю.

2 ответа

Кажется, что код, как в следующих работах. Мне просто интересно, есть ли какие-нибудь узкие места, накладные расходы, или следующее прекрасно работает:

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*. Мне интересно, можно ли что-нибудь улучшить.

Благодарю.

Два типа безопасных способа сделать это:

  • Напишите 4 метода, которые вы уже отклонили; а также
  • Тестовое задание T в if заявления.

Это может выглядеть примерно так:

#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.

Другие вопросы по тегам