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).
No hay necesidad de crear una nueva clase. Intenta usar xany https://sourceforge.net/projects/extendableany/?source=directory xany class permite agregar nuevos métodos a la funcionalidad existente de cualquiera. Por cierto hay un ejemplo en la documentación que hace exactamente lo que quieres.
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.