问题方法:
template <typename T>
void SerializableScalar<T>::deserialize(const Json::Value& token)
{
if (isDeserilizationPossible(token)){
if (token.isInt())
{
myValue = token.asInt();
}
if (token.isDouble())
{
myValue = token.asDouble();
}
if (token.isString())
{
myValue = token.asString().c_str();
}
if (token.isBool())
{
myValue = token.asBool();
}
}
}
其中token可以包含string,int,double,bool等类型。
然后我创建对象并使用反序列化方法
Json::Value token(55);
当我创建对象时:
SerializableScalar<int> object;
object.deserialize(token);
我得到编译错误,因为当我创建T = int的对象时;在我的deserialize方法中,我无法将字符串转换为int,即使json不保存字符串的值,couse编译器检查所有分支....现在我要求你的建议。这有什么解决方案吗?我试图重载deserialize方法,它的工作,但我不想要单独的4种方法,我正在寻找更清洁的东西。
IsDeserilizationPossible方法
template <typename T>
bool SerializableScalar<T>::isDeserilizationPossible(const Json::Value& token)
{
if (!token.isArray() && !token.isObject() && !token.empty())
{
myIsDeserialize = true;
return true;
}
throw std::exception("Some exception");
}
其他信息:
在cLass中只是空构造函数和变量myValue持有类型的T. point是反序列化Json,设置类型为T的值。客户端知道他想要的类型,所以他使用getMethod获取Serializable对象的值;多数民众赞成,我尝试专业化它已经工作正常,但我只是好奇,如果有更多我可以使用,所以我不需要重载方法。
错误::
error C2440: '=' : cannot convert from 'const char *' to 'double'
error C2440: '=' : cannot convert from 'const char *' to 'int'
答案 0 :(得分:1)
不幸的是,没有办法为每种相关类型创建专业化。以下是将特化项委托给辅助类的一种方法:
template<typename T>
struct Helper
{
static inline bool is(const Json::Value&);
static inline T as(const Json::Value&);
};
template<> bool Helper<int>::is(const Json::Value& tok)
{ return tok.isInt(); }
template<> bool Helper<double>::is(const Json::Value& tok)
{ return tok.isDouble(); }
template<> bool Helper<string>::is(const Json::Value& tok)
{ return tok.isString(); }
template<> bool Helper<bool>::is(const Json::Value& tok)
{ return tok.isBool(); }
template<> int Helper<int>::as(const Json::Value& tok)
{ return tok.asInt(); }
template<> double Helper<double>::as(const Json::Value& tok)
{ return tok.asDouble(); }
template<> string Helper<string>::as(const Json::Value& tok)
{ return tok.asString(); }
template<> bool Helper<bool>::as(const Json::Value& tok)
{ return tok.asBool(); }
template<typename T>
void SerializableScalar<T>::deserialize(Json::Value& tok)
{
if ( Helper<T>::is(tok) )
myValue = Helper<T>::as(tok);
}
答案 1 :(得分:1)
这应该是一个评论,但它太长了:
编译和运行时数量不能很好地融合在一起。我想你已经发现将类型int
硬编码到序列化中会感到不舒服。
SerializableScalar<int> object;
如果它包含字符串,该怎么办?您想要对每种可能的类型进行反序列化吗?
SerializableScalar<int> object_int;
SerializableScalar<double> object_double;
SerializableScalar<std::string> object_string;
if(object_int) //check whether int is filled
{
//...
}
else if (object_double)
{
//...
}
接下来,你想以递归方式做到这一点(Json可以包含其他Json&#39; s)?这在我看来是不切实际的。
唯一的例外是您确切知道Json的内容。然后,可以编写一般的包装器函数(比类imo更舒服),例如
template<typename T>
auto get_value(Json::Value const& json) {}
template<>
auto get_value<int>(Json::Value const& json) { return json.as_int(); }
template<>
auto get_value<bool>(Json::Value const& json) { return json.as_bool(); }
并根据你的Json结构应用它。请注意,到目前为止,我还没有添加任何类型检查,例如json.is_int()
。合并它的两种可能性:
首先,如果它不是int
,则返回默认值:
constexpr int DEFAULT = -1;
template<>
auto get_value<int>(Json::Value const& json)
{
return json.is_int() ? json.as_int() : DEFAULT;
}
其次,稍微复杂一点,你可以返回一个optional<int>
,如果没有填充json,它就处于空状态。
但是,在一般情况下,当您不知道内容或内容即将发生变化时,必须接受Json的多类型和相应的模型。基本方法是使用boost::variant
加上适当的visitor。
答案 2 :(得分:0)
一种可能性是创造一个全能的过载:
void Json::Value::operator=(...)
{
assert( false && "this should never be called" );
}
这在重载分辨率方面具有最低优先级,但是性能分配将不再产生编译时错误,因此请将其视为快速修复。