Automagically
        
      
      
      
       Cereal provides a separate portable binary archive serializer which takes care of that. Most of the time we dont care though. Even current urho serializer does not.
      
      
       And a small update on progress:
      
      class CerealTest : public Serializable
{
    URHO3D_OBJECT(CerealTest, Serializable);
    virtual void Serialize(::cereal::BinaryInputArchive& ar) { ar(*this); }
    virtual void Serialize(::cereal::BinaryOutputArchive& ar) { ar(*this); }
    virtual void Serialize(::cereal::PortableBinaryInputArchive& ar) { ar(*this); }
    virtual void Serialize(::cereal::PortableBinaryOutputArchive& ar) { ar(*this); }
    virtual void Serialize(::cereal::XMLInputArchive& ar) { ar(*this); }
    virtual void Serialize(::cereal::XMLOutputArchive& ar) { ar(*this); }
    virtual void Serialize(::cereal::JSONInputArchive& ar) { ar(*this); }
    virtual void Serialize(::cereal::JSONOutputArchive& ar) { ar(*this); }
public:
    explicit CerealTest(Context* context) : Serializable(context)
    {
    }
    static void RegisterObject(Context* context)
    {
        context->RegisterFactory<CerealTest>();
        URHO3D_ATTRIBUTE("Integer Foo", int, foo_, 0, AM_DEFAULT);
    }
    template<typename Archive>
    void serialize(Archive& ar)
    {
        ar(::cereal::make_nvp(BaseClassName::GetTypeNameStatic().CString(), cereal::base_class<BaseClassName>(this))
            ,CEREAL_NVP(hash_)
            ,CEREAL_NVP(vector2_)
        );
    }
    int foo_ = 0;
    Vector2 vector2_{12, 34};
    StringHash hash_;
};
      
       Produces:
      
      <?xml version="1.0" encoding="utf-8"?>
<root>
	<value>
		<value name="Serializable">
			<value name="Integer Foo">123</value>
		</value>
		<value name="hash_">555</value>
		<value name="vector2_">12 34</value>
	</value>
</root>
      [
    {
        "Serializable": {
            "Integer Foo": 1234
        },
        "hash_": 555,
        "vector2_": [
            12.0,
            34.0
        ]
    }
]
      
       XML output required some modifications to cereal, but they are pretty minor. Overall i am pretty happy with output. There are a few things to note.
      
      
       Cereal has support for polymorphic types. Problem with that is that it requires extra macro to be used at global scope. This example would have required following:
      
      CEREAL_REGISTER_TYPE(CerealTest);
CEREAL_REGISTER_POLYMORPHIC_RELATION(CerealTest::BaseClassName, CerealTest)
      
       This sucks as it is extra bookkeeping user must not forget about. Besides we already have this information recorded using
       
        URHO3D_OBJECT()
       
       macro. Those macros are also used to enable cereal to serialize object from most derived to the base. I could not get that part working however, so as a workaround i added bunch of
       
        virtual void Serialize()
       
       that call a correct templated serialization function variant. At least these can be hidden behind
       
        URHO3D_OBJECT()
       
       macro if need be.
      
      
       Lets look at actual serialization function:
      
          template<typename Archive>
    void serialize(Archive& ar)
    {
        ar(::cereal::make_nvp(BaseClassName::GetTypeNameStatic().CString(), cereal::base_class<BaseClassName>(this))
            ,CEREAL_NVP(hash_)
            ,CEREAL_NVP(vector2_)
        );
    }
      
       Single function handles serialization
       
        and
       
       deserialization to any number of supported formats. I am still stunned about this
        
       
        make_nvp()
       
       (stands for “make name-value-pair”) for serialization of base class is not strictly necessary, but it makes output nicer. One thing you may find confusing is that
       
        Integer Foo
       
       attribute is registered to
       
        CerealTest
       
       class, but it is serialized as part of
       
        Serializable
       
       class. This is because
       
        Serializable
       
       class manages all attributes. This could probably be solved though.
      
      
       As you see
       
        StrignHash
       
       and
       
        Vector2
       
       types are serialized transparently to the user as well. Their values in XML and JSON look user-friendly, but it comes at a cost of implementing serialization a little bit differently for every format.
      
      
// Vector2
template <class Archive> inline
void CEREAL_SAVE_FUNCTION_NAME(Archive& ar, const Urho3D::Vector2& value)
{
    if (std::is_same<Archive, JSONInputArchive>::value || std::is_same<Archive, JSONOutputArchive>::value)
    {
        size_type size = 2;
        ar(make_size_tag(size));    // Make json use array. Without this output would be {"value0": 12.0, "value1": 34.0}
        ar(value.x_, value.y_);
    }
    else if (std::is_same<Archive, XMLInputArchive>::value || std::is_same<Archive, XMLOutputArchive>::value)
        ar(std::string(value.ToString().CString()));    // Serialize as string to make everything fit into one xml tag.
    else
        ar(value.x_, value.y_);  // Binary archives, at least they are trivial
}
template <class Archive> inline
void CEREAL_LOAD_FUNCTION_NAME(Archive& ar, Urho3D::Vector2& value)
{
    if (std::is_same<Archive, JSONInputArchive>::value || std::is_same<Archive, JSONOutputArchive>::value)
    {
        size_type size = 2;
        ar(make_size_tag(size));
        ar(value.x_, value.y_);
    }
    else if (std::is_same<Archive, XMLInputArchive>::value || std::is_same<Archive, XMLOutputArchive>::value)
    {
        std::string text;
        ar(text);
        value = Urho3D::ToVector2(text.c_str());
    }
    else
        ar(value.x_, value.y_);
}
URHO3D_SERIALIZE_PLAIN(XML, Urho3D::Vector2);  // Hint cereal that this type is simple enough that it does not need multi-level xml tree.
      
       For time being i removed versioning. This matter still needs some thought. Object version has has also to be declared with a macro
       
        CEREAL_CLASS_VERSION(Type, Version)
       
       at global scope. Maybe versioning could be achieved by defining
       
        using Version = 1;
       
       in the class and have cereal use that automatically if it is present.
      
      
      
       Conclusion: current implementation is very early WIP, but it holds promise to satisfy all requirements. Implementation that is on par with current features is possible now (although file formats would change). More concerning part is support for polymorphism, so we could also serialize any subclasses of
       
        Serializable
       
       stored in shared pointers and have them restored properly. This would likely require some serious work reimplementing bulk of cereal’s features to use metadata defined in
       
        URHO3D_OBJECT()
       
       macro.