0

我想編寫一系列模板函數來序列化和反序列化對象。我已經完成了序列化部分和一切工作:如何在C++中對稱地實現序列化和反序列化模板函數

#ifndef SERIALIZE_H 
#define SERIALIZE_H 

#include <string> 
#include <vector> 
#include <unordered_set> 
#include <unordered_map> 
#include <memory> 

inline std::string to_json(int value) { 
    return std::to_string(value); 
} 


inline std::string to_json(long value) { 
    return std::to_string(value); 
} 


inline std::string to_json(double value) { 
    return std::to_string(value); 
} 


inline std::string to_json(const std::string& myStr) { 
    return "\"" + myStr + "\""; 
} 


template <typename T> 
std::string to_json(const std::vector<T>& vec) { 
    std::string json("["); 

    for(auto &i : vec) { 
     json += to_json(i); 
     json += ","; 
    } 

    if (!vec.empty()) json.pop_back(); 
    json += "]"; 
    return json; 
} 


template <typename T> 
std::string to_json(const std::unordered_set<T>& mySet) { 
    std::string json("["); 

    for(const auto& i : mySet) { 
     json += to_json(i); 
     json += ","; 
    } 

    if (!mySet.empty()) json.pop_back(); 
    json += "]"; 
    return json; 
} 


template <typename K, typename V> 
std::string to_json(const std::unordered_map<K, V>& myMap) { 
    std::string json("{"); 

    for(const auto& i : myMap) { 
     json += to_json(i.first); 
     json += ":"; 
     json += to_json(i.second); 
     json += ","; 
    } 

    if (!myMap.empty()) json.pop_back(); 
    json += "}"; 
    return json; 
} 

#endif //SERIALIZE_H 

serialize.h可序列化的各種組合,如unordered_map<string, vector<int>>

現在我不知道如何遞歸實現反序列化函數來支持任意組合。

以下是我deserialize.h不工作:

#ifndef DESERIALIZE_H 
#define DESERIALIZE_H 

#include <string> 
#include <rapidjson/document.h> 


template<typename T> 
T from_json(const std::string &json); 

template<> 
int from_json(const std::string &json) { 
    return std::stoi(json); 
} 

template<> 
long from_json(const std::string &json) { 
    return std::stol(json); 
} 

template<> 
double from_json(const std::string &json) { 
    return std::stod(json); 
} 

template<> 
std::string from_json(const std::string &json) { 
    return json.substr(1, json.size()-1); 
} 

// 
template<typename T> 
std::vector<T> from_json(const std::string& json) { 
    rapidjson::Value jsonValue; 
    { 
     const std::string &input = "{\"input\":" + json + "}"; 
     rapidjson::Document document; 
     document.Parse(input.c_str()); 
     jsonValue = document["input"]; 
    }; 
    std::vector<T> vec; 
    assert(jsonValue.IsArray()); 

    for (rapidjson::SizeType i = 0; i < jsonValue.Size(); i++) { 
     int element = from_json<T>(std::string(jsonValue[i].GetString())); 
     vec.push_back(element); 
    } 
    return vec; 
} 

#endif //DESERIALIZE_H 

rapidjson是一個C++ JSON庫,https://github.com/miloyip/rapidjson

然後,如果我嘗試反序列化JSON字符串:

#include "deserialize.h> 

int main() { 
    auto vec1 = from_json<std::vector<int>>(std::string("[1,2,3]")); 
    return 0; 
} 

它會拋出編譯錯誤:

error: call of overloaded ‘from_json(std::string)’ is ambiguous 

似乎沒有辦法像序列化一樣輕鬆地實現反序列化函數。

任何想法?

+0

相關:http://www.gotw.ca/publications/mill17.htm。具體而言,您定義的兩個(主要)函數模板之間沒有更專門化的關係,因爲它們只在返回類型上有所不同。如果你想保持接口的一個解決方案是發送到一個'template T from_json(標籤,const std :: string&);模板 std :: vector from_json(tag >,const std :: string&);'重載集合,其中可以基於第一個(虛擬/標記)參數建立*更多專用關係。 – dyp

+0

我不會打擾那些內聯。轉換字符串不是一個簡單的操作。 –

+0

你希望它叫'模板 牛逼from_json(常量的std :: string &json);',或者'模板 的std ::矢量 from_json(常量的std :: string和JSON)'?也就是說,它應該返回'(std :: vector )'(來自第二個模板)? – immibis

回答

2

您試圖重載相同的函數(from_json(...)),每次都使用相同的參數和不同的返回類型。這不合法。 對於重載,您需要不同的參數類型或參數號。

Instead of 
template<> 
double from_json(const std::string &json) { 
    return std::stod(json); 
} 

template<> 
std::string from_json(const std::string &json) { 
    return json.substr(1, json.size()-1); 
} 

也許試試這個,或者至少這應該是總體思路:

template<> 
void from_json(const std::string &json, double *out_value) { 
    *out_value = std::stod(json); 
} 

template<> 
void from_json(const std::string &json, std::string *out_value) { 
    out_value = json.substr(1, json.size()-1); 
} 

我肯定有錯誤,但我認爲這樣就可以工作(如果你解決這些問題)

+1

OP是混合*函數模板顯式特化* *函數重載*特別是'template <> double from_hson(const std :: string &json);''是模板的from_json(const std :: string &json);'主模板的顯式特化。 – dyp

+0

使用不同的參數類型可以工作,這是肯定的,但我仍然想對返回類型進行模板特化。 – soulmachine

相關問題