用于创建SerializerManager的模板魔术

时间:2014-04-25 21:28:33

标签: c++ templates

我正在创建一个编辑数据的应用程序,然后需要以各种格式存储它。问题是应用程序是使用插件架构构建的 记住,所以我不知道哪些格式或哪些对象需要事先存储。

我想要完成的是一个SerializeManager,您可以在其中动态注册支持的格式。

目标是能够创建一个对象,然后指定模板特化支持的格式。 例如:

template<typename Type, typename Format>
void serialize(const Type& type, const Format& format)
{
}

class IFormat
{
public:
    virtual ~IFormat(){} 
};

class XmlFormat : public IFormat
{

};

class BinaryFormat : public IFormat
{

};

class MyDataToStore
{
public:
    int m_data1; //Data to store
    string m_data2; //Data to store
};

template<>
void serialize(const MyDataToStore& type, const XmlFormat& format)
{
    //Serialization code goes here
}

我现在的目标是创建一个SerializeManager来管理所有格式并调用正确的特化。我希望它能像这样工作:

int main()
{
    SerializeManager man;
    man.RegisterFormat(".xml", std::shared_ptr<IFormat>(new XmlFormat())); // Where .xml is a key

    MyDataToStore obj;

    man.Store<MyDataToStore>(".xml", obj); //where .xml is a key
}

目标是在上面的MyDataToStore,Xml特化中结束,而不必在Store函数中将格式指定为模板参数。这甚至可能吗?我已经尝试在IFormat类中使用纯虚函数来调用子类中的serialize函数,但由于虚函数无法使用模板,因此我松开MyDataToStore并调用默认函数。

问候!

编辑:

如果有人想知道我使用以下解决方案解决了问题。我不想在序列化/反序列化时只需指定扩展名。这是我的结果。

#include <string>

template<typename Formatter, typename Type>
void serialize(Formatter& format, Type& type)
{
static_assert(false, "No known serializer function found");
}

template<typename Formatter, typename Type>
void deserialize(Formatter& format, Type& type)
{
static_assert(false, "No known deserializer function found");
}

class SerializeManager
{
public:
    SerializeManager(){}
    virtual ~SerializeManager(){}

    template<typename Type, typename Formatter>
    bool Serialize(std::string filepath, Type & t)
    {
        Formatter format(filepath);
        format.setManager(this);
        serialize<Formatter, Type>(format, t);
        return true;
    }

    template<typename Type, typename Formatter>
    bool Serialize(Formatter& format, Type& t)
    {
        serialize(format, t);
        return true;
    }

    template<typename Type, typename Formatter>
    bool Deserialize(std::string filepath, Type & t)
    {
        Formatter format(filepath);
        format.setManager(this);
        deserialize<Formatter, Type>(format, t);
        return true;
    }

    template<typename Type, typename Formatter>
    bool Deserialize(Formatter& format, Type& t)
    {
        deserialize(format, t);
        return true;
    }


private:

};

class FormatterBase
{
public:
    void setManager(SerializeManager* man)
    {
        m_manager = man;
    }

    SerializeManager* getManager()
    {
        return m_manager;
    }

private:
    SerializeManager* m_manager;
};

如果没有找到专门的函数,static_assert会帮助引发编译器错误。似乎运作良好。用法:

#include "SerializeManager.h"

struct Human
{
    template<typename T, typename S>
    friend void serialize(T& t, S& s);

    template<typename T, typename S>
    friend void deserialize(T& t, S& s);

    Human(int age, std::string name) : m_age(age), m_name(name){}

private:

    int m_age;
    std::string m_name;
};

class XmlSerializer : public FormatterBase
{
public:
XmlSerializer(std::string filepath){}

void NewNode(std::string name){}
};

template<>
void serialize(XmlSerializer& serial, Human& human)
{
    //Do the serialization
}

int main()
{
    SerializeManager man;
    Human åke(15, "Åke");
    man.Serialize<Human, XmlSerializer>("file.xml", åke);
}

1 个答案:

答案 0 :(得分:2)

我认为你在步行之前就已经开始了。

您需要的是中间格式。它可以是二进制的,它可以是名称/值对的树,它并不重要。什么重要是所有内容都可以序列化为这种中间格式。

然后,在这种中间格式中编写序列化器是一个简单的(ha!)案例。你可以想出Xml,Json,Binary或其他任何深奥的格式。

关键是众所周知且定义明确的中间层。一旦你拥有了它,那么在另一端发生的事情并不重要。