我需要撰寫一個決議 JSON 物件的函式。為了方便起見,我決定使用模板來做到這一點。
所以,我的函式如下所示:
template<typename ValueType>
ValueType get(const Json& json);
對于我想從 JSON 接收的每種型別的值,都有一個專門化:
template<>
uint8_t get(const Json& json);
template<>
double get(const Json& json);
template<>
std::string get(const Json& json);
...
現在我想擴展這個功能并添加接收元素容器的能力。據我了解,為了實作這一點,我需要為每種容器型別和每種值型別添加專業化:
template<>
std::vector<uint8_t> get(const Json& json);
template<>
std::vector<std::string> get(const Json& json);
...
由于 N * N 復雜性,這絕對不方便。而不是這樣做,我想要這樣的東西:
template<typename ValueType>
std::vector<ValueType> get<std::vector<ValueType>>(const Json& json);
甚至這個:
template<template<typename...> class Container, typename ValueType>
Container<ValueType> get(const Json& json);
但是,如果我嘗試撰寫此類模板,則會收到錯誤訊息:
錯誤:函式模板部分特化 'getstd::vector<_RealType >' 不允許 std::vector getstd::vector<ValueType>(const Json& json);
我應該如何重構函式以實作我的目標?
uj5u.com熱心網友回復:
您可能會使用標簽調度程式助手(因此多載而不是專門化):
template <typename T>
struct tag{};
uint8_t get_helper(tag<uint8_t>, const Json& json);
double get_helper(tag<double>, const Json& json);
std::string get_helper(tag<std::string>, const Json& json);
template <typename ValueType>
std::vector<ValueType> get_helper(tag<std::vector<ValueType>>, const Json& json)
{
// ... use get_helper(tag<ValueType>{}, sub_json);
}
template<typename ValueType>
ValueType get(const Json& json)
{
return get_helper(tag<ValueType>{}, json);
}
uj5u.com熱心網友回復:
可以避免 IMO 使用模板。
將代碼從回傳值更改為通過參考傳遞,它變得簡單而干凈:
void get(const Json& json, uint8_t& retVal);
void get(const Json& json, double& retVal);
void get(const Json& json, std::string& retVal);
要涵蓋std::vector口味,您可以使用此模板:
template<typename T>
void get(const Json& json, std::vector<T>& retVal)
{
if (json.isArray()) {
auto jarray = json.toArray();
retVal.resize(jarray.size());
for (size_t i = 0; i < retVal.size(); i) {
get(jarray[i], retVal[i]);
}
}
}
如果您仍然需要模板,則上述方法可用于僅使用模板的默認實作來解決您的問題:
template<typename ValueType>
ValueType get(const Json& json);
{
ValueType retVal;
get(json, retVal); // use overloads from above
return retVal;
}
這樣,默認模板實作就可以完成所需的一切。擴展也很簡單。
uj5u.com熱心網友回復:
這個答案假設c 17變數模板。
撰寫一個型別模板,并部分專門化該型別模板。將您需要的決議函式作為operator()成員放入部分型別模板特化中。宣告get為實體化該型別模板的變數模板。
template<typename Ret>
struct get_impl;
template<typename Elem>
struct get_impl<std::vector<Elem>> {
auto operator()(const Json&) -> std::vector<Elem>;
};
template<>
struct get_impl<std::string> {
auto operator()(const Json&) -> std::string;
};
template<typename Ret>
inline constexpr auto get = get_impl<Ret>{};
順便說一句,這類似于實作自定義點物件的方式。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/433964.html
上一篇:輸入具有特定成員函式的多載函式
