编译错误,对成员变量进行多重赋值的方法,模板类C ++

时间:2016-02-17 06:48:27

标签: c++ c++11 visual-c++ c++14

问题方法:

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'

3 个答案:

答案 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的内容在编译时已知

唯一的例外是您确切知道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" );
}

这在重载分辨率方面具有最低优先级,但是性能分配将不再产生编译时错误,因此请将其视为快速修复。