class Test : public Serializable { public: int SomeInt = 666; float SomeFloat = 42.2; string SomeString = "Hello My Little Pony"; private: serialize(SomeInt); serialize(SomeFloat); serialize(SomeString); };
struct Test { string SomeString = "Hello My Little Pony"; function<void()> SomeFunc = [this]() { cout << SomeString; }; };
class Serializable { protected: typedef function<void(const string&)> Func; struct SerializerPair { Func Serializer; Func Deserializer; }; char Add(string _key, Func _serializer, Func _deserializer) { auto& lv_Pair = m_Serializers[_key]; lv_Pair.Serializer = _serializer; lv_Pair.Deserializer = _deserializer; } public: virtual void Serialize() { for (auto& lv_Ser : m_Serializers) lv_Ser.second.Serializer(lv_Ser.first); } virtual void Deserialize() { for (auto& lv_Ser : m_Serializers) lv_Ser.second.Deserializer(lv_Ser.first); } private: map<string, SerializerPair> m_Serializers; };
class TestClass : public Serializable { public: int SomeInt = 666; private: char SomeIntSer = Add ( "SomeInt", [this](const string& _key) { ::Serialize(_key, SomeInt); }, [this](const string& _key) { ::Deserialize(_key, SomeInt); } ); };
#define UNNAMED_IMPL(x, y) UNNAMED_##x##_##y #define UNNAMED_DECL(x, y) UNNAMED_IMPL(x, y) #define UNNAMED UNNAMED_DECL(__LINE__ , __COUNTER__) // UNNAMED #define serialize(x) char UNNAMED = Add \ ( \ #x, \ [this](const string& _key) \ { \ ::Serialize(_key, x); \ }, \ [this](const string& _key) \ { \ ::Deserialize(_key, x); \ } \ )
class TestClass : public Serializable { public: int SomeInt = 666; private: serialize(SomeInt); };
template<class Container> class Serializable { protected: typedef function<void(const string&, Container&)> Func; struct SerializerPair { Func Serializer; Func Deserializer; }; Container* ContainerInf = 0; char Add(string _key, Func _serializer, Func _deserializer) { auto& lv_Pair = m_Serializers[_key]; lv_Pair.Serializer = _serializer; lv_Pair.Deserializer = _deserializer; return 0; } public: virtual void Serialize(Container& _cont) { for (auto& lv_Ser : m_Serializers) lv_Ser.second.Serializer(lv_Ser.first, _cont); } virtual void Deserialize(Container& _cont) { for (auto& lv_Ser : m_Serializers) lv_Ser.second.Deserializer(lv_Ser.first, _cont); } private: map<string, SerializerPair> m_Serializers; };
template<bool UNUSE> struct SerializerEX {}; template<> struct SerializerEX < false > { template<class T, class Cont, class UNUSE> void Serialize(const string& _key, T& _val, Cont& _cont, UNUSE) { ::Serialize(_key, &_val, _cont); } template<class T, class Cont, class UNUSE> void Deserialize(const string& _key, T& _val, Cont& _cont, UNUSE) { ::Deserialize(_key, &_val, _cont); } }; template<> struct SerializerEX < true > { template<class T, class Cont, class UNUSE> void Serialize(const string& _key, T& _val, Cont& _cont, UNUSE) { ::Serialize(_key, (UNUSE)&_val, _cont); } template<class T, class Cont, class UNUSE> void Deserialize(const string& _key, T& _val, Cont& _cont, UNUSE) { ::Deserialize(_key, (UNUSE)&_val, _cont); } };
#define serialize(x) char UNNAMED = Add \ ( \ #x, \ [this](const string& _key, ClearType<decltype(ContainerInf)>::Type& _cont) \ { \ SerializerEX \ < \ CanCast \ < \ Serializable< ClearType<decltype(ContainerInf)>::Type >, \ ClearType<decltype(x)>::Type \ >::Result \ > EX; \ EX.Serialize(_key, x, _cont, (Serializable< ClearType<decltype(ContainerInf)>::Type >*)0); \ }, \ [this](const string& _key, ClearType<decltype(ContainerInf)>::Type& _cont) \ { \ SerializerEX \ < \ CanCast \ < \ Serializable< ClearType<decltype(ContainerInf)>::Type >, \ ClearType<decltype(x)>::Type \ >::Result \ > EX; \ EX.Deserialize(_key, x, _cont, (Serializable< ClearType<decltype(ContainerInf)>::Type >*)0); \ } \ )
struct Float3 { float X = 0; float Y = 0; float Z = 0; }; class Transform : public Serializable < pugi::xml_node > { public: Float3 Position; Float3 Rotation; Float3 Scale; private: serialize(Position); serialize(Rotation); serialize(Scale); }; class TestClass : public Serializable<pugi::xml_node> { public: int someInt = 0; float X = 0; string ObjectName = "Test"; Transform Transf; map<string, float> NamedPoints; TestClass() { NamedPoints["one"] = 1; NamedPoints["two"] = 2; NamedPoints["three"] = 3; NamedPoints["PI"] = 3.1415; } private: serialize(X); serialize(ObjectName); serialize(Transf); serialize(NamedPoints); };
void Test() { { TestClass lv_Test; lv_Test.ObjectName = "Hello my little pony"; lv_Test.X = 666; lv_Test.Transf.Scale.X = 6; lv_Test.Transf.Scale.Y = 6; lv_Test.Transf.Scale.Z = 6; pugi::xml_document doc; auto lv_Node = doc.append_child("Serialization"); lv_Test.Serialize(lv_Node); doc.save_file(L"Test.xml"); doc.save(cout); } { pugi::xml_document doc; doc.load_file(L"Test.xml"); auto lv_Node = doc.child("Serialization"); TestClass lv_Test; lv_Test.Deserialize(lv_Node); cout << "Test passed : " << ( lv_Test.X == 666 && lv_Test.ObjectName == "Hello my little pony" && lv_Test.Transf.Scale.X && lv_Test.Transf.Scale.Y && lv_Test.Transf.Scale.Z ); } }
<?xml version="1.0"?> <Serialization> <NamedPoints> <PI value="3.1415" /> <one value="1" /> <three value="3" /> <two value="2" /> </NamedPoints> <ObjectName value="Hello my little pony" /> <Transf> <Position x="0" y="0" z="0" /> <Rotation x="0" y="0" z="0" /> <Scale x="6" y="6" z="6" /> </Transf> <X value="666" /> </Serialization> Test passed : 1
void Serialize(const string& _key, T* _val, xml_node & _node)
void Serialize(const string& _key, T* _val, xml_node & _node,...)
void Serialize(const string& _key, T* _val, xml_node & _node, Widget*) { ... }
#define serialize(x) char UNNAMED = Add \ ( \ #x, \ [this](const string& _key, ClearType<decltype(ContainerInf)>::Type& _cont) \ { \ ::Serialize(_key, &x, _cont, (ClearType<decltype(x)>::Type*)0); \ }, \ \ [this](const string& _key, ClearType<decltype(ContainerInf)>::Type& _cont) \ { \ ::Deserialize(_key, &x, _cont, (ClearType<decltype(x)>::Type*)0); \ } \ )
Source: https://habr.com/ru/post/244963/
All Articles