library c++ serialization boost-any

library - C++-boost:: cualquier serialización



boost windows binary (4)

Por lo que yo entiendo, no hay soporte de serialización ( boost::serialization , en realidad) para boost::any placeholder.

¿Alguien sabe si hay una manera de serializar un boost::any personalizado boost::any entidad?

El problema aquí es obvio: boost::any usa marcadores de posición basados ​​en plantillas para almacenar objetos y typeid para comprobar si boost::any_cast es apropiado.

Por lo tanto, existe un placeholder superclase abstracto personalizado y clases derivadas basadas en plantillas personalizadas, que se crean de la siguiente manera:

template <T> custom_placeholder : public placeholder { virtual std::type_info type() const { return typeid(T); } virtual ... };

Obviamente, esto trae algunos problemas incluso cuando se piensa en serializar esto. Tal vez alguien sabe algún truco para hacer ese tipo de serialización (y, por supuesto, deserialización adecuada)?

Gracias


No es posible en absoluto, al menos para tipos arbitrarios. Tenga en cuenta que tal vez podría serializar usando algún código complicado (como encontrar el tamaño de los elementos contenidos en el), pero el código depende de que el compilador coloque de forma estática el tipo de código y los tipos adecuados dentro del marcador de posición. Seguramente no puedes hacer eso en la deserialización en C ++, ya que el tipo que obtendrías de la deserialización no se conoce en tiempo de compilación (como lo requiere el nuevo boost::any ).

La mejor solución es construir algún tipo de tipo especializado para los tipos exactos de elementos que va a serializar. Entonces, puede tener casos especiales para el tipo real de elemento que se está deserializando, pero tenga en cuenta que cada serialización / deserialización del tipo de elemento debe escribirse físicamente como código estático de C ++.

PD. Algunos otros sugirieron usar boost::variant como una representación de este tipo especializado que contiene los tipos exactos que vas a serializar. Sin embargo, necesita una forma de discernir el tipo exacto de deserialización (tal vez asignar identificadores a los tipos en la variante).



Si quieres quedarte con boost :: any, no estoy seguro, pero puedes escribir tu propio "boost :: any". Estoy usando este código para métodos proxy para pasar los parámetros.

#include <iostream> #include <boost/smart_ptr/scoped_ptr.hpp> #include <boost/shared_ptr.hpp> #include <boost/serialization/access.hpp> #include <boost/serialization/shared_ptr.hpp> #include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> #include <boost/serialization/export.hpp> #include <sstream> class my_placeholder { public: virtual ~my_placeholder(){} my_placeholder(){} private: friend class boost::serialization::access; template<class Archive> void serialize(Archive & ar, const unsigned int version) { // serialize base class information //ar & boost::serialization::base_object<bus_stop>(*this); //ar & m_placeholder; } }; template<typename T> class my_derivedplaceholder: public my_placeholder { public: my_derivedplaceholder() { } my_derivedplaceholder(T &value) { m_value=value; } T m_value; private: friend class boost::serialization::access; template<class Archive> void serialize(Archive & ar, const unsigned int version) { // serialize base class information ar & boost::serialization::base_object<my_placeholder>(*this); ar & m_value; } }; BOOST_CLASS_EXPORT_GUID(my_derivedplaceholder<int>, "p<int>"); class my_any { public: my_any() { } template<typename T> my_any(const T &value) { m_placeholder.reset(new my_derivedplaceholder<T>(const_cast<T&>(value))); } template<typename T> void operator=(const T &value) { m_placeholder.reset(new my_derivedplaceholder<T>(const_cast<T&>(value))); } protected: friend class boost::serialization::access; template<class Archive> void serialize(Archive & ar, const unsigned int version) { // serialize base class information //ar & boost::serialization::base_object<bus_stop>(*this); ar & m_placeholder; } template<typename T> friend T my_anycast(my_any &val); boost::shared_ptr<my_placeholder> m_placeholder; }; template<typename T> T my_anycast(my_any &val) { boost::shared_ptr<my_derivedplaceholder<T>> concrete=boost::dynamic_pointer_cast<my_derivedplaceholder<T>>(val.m_placeholder); if (concrete.get()==NULL) throw std::invalid_argument("Not convertible"); return concrete->m_value; } void main() { my_any m=10; int a=my_anycast<int>(m); std::cout << a << std::endl; std::stringstream ss,ss2; boost::archive::text_oarchive oa(ss); oa << m; boost::archive::text_iarchive ia(ss); my_any m2; ia >> m2; std::cout << my_anycast<int>(m2) << std::endl; }


Suponiendo que tiene que usar boost::any y no puede cambiar a la variant , una solución basada en map<type_info const*, string(*)(any)> podría hacerlo.

Tienes que inicializar en tiempo de ejecución un map con todos los tipos que planeas usar. Por supuesto, puede usar algo similar a

template <typename T> struct any_serializer { static string perform(any a) { T const& x = any_cast<T const&>(a); stringstream out; out << x; return out.str(); } };

y any_serializer<T>::perform el mapa con direcciones de any_serializer<T>::perform bajo la clave &typeid(T) . Puedes especializar la clase any_serializer y usar algunas macros (feas) para poblar el mapa.

Más difícil es, por supuesto, la deserialización. No he boost::lexical_cast un vistazo a boost::lexical_cast por un tiempo, quizás pueda brindar alguna ayuda. Me temo que esto es totalmente dependiente del problema. Sin embargo, solo necesita una función, que toma una string y devuelve una any . Es posible que también desee anteponer su cadena de salida con un identificador de tipo personalizado.