¿Impulsar MPL para generar código para la serialización de objetos?

Quiero generar código de serialización / deserialización para

class Object
{
    string a;
    int b;
    long c;
    char d;
};

mirando una secuencia mpl, pero necesito poder identificar el objeto y recuperarlo también, no puedo averiguar cómo obtendría los nombres de sus miembros, tengo que saberlo?

el código debería verse como

void SerializeObject(ostream os)
{
   serialize(object.a, os);
   serialize(object.b, os);

   //serialize(object.member, os);
}

Quiero generar el código anterior por el usuario que solo define una secuencia mpl correspondiente al diseño del objeto, ¿es factible? ¿Me pueden dar algunas sugerencias?

mi objetivo es:

El usuario define mpl::vector<String, int, long, char> para el objeto anterior y mi metaprogram puede generar el codificado necesario.

preguntado el 16 de mayo de 11 a las 19:05

No creo que puedas obtener los nombres de tus miembros sin un hackeo serio. Considere lo que sucede si tiene dos entradas, por ejemplo. ¿Cómo sabría boost :: mpl cuál int es cuál? -

@Boaz, no me importa mientras tenga tanto el ints en la misma secuencia en que los pasé. -

3 Respuestas

Considera un boost::fusiony usa la macro BOOST_FUSION_ADAPT_STRUCT() para promover su estructura a una secuencia de fusión (acceso aleatorio), por ejemplo, una vez que haya definido la estructura anterior, puede hacer algo como

BOOST_FUSION_ADAPT_STRUCT(
    Object,
    (std::string, a)
    (int, b)
    (long, c)
    (char, d)
)

Ahora que se ha promocionado, simplemente puede utilizar un for_each para iterar sobre los miembros, algo como:

template<typename archive>
struct serializer {
   serializer(archive& ar):ar(ar) {}

   template<typename T>
   void operator()(const T& o) const {
      ar & o;  // assuming binary for example...
   }
   archive& ar;
};

template<typename archive, typename sequence>
void serialize(archive& ar, sequence const& v) {
   boost::fusion::for_each(v, serializer<archive>(ar));
}

Para usarlo, debería ser tan simple como:

Object foo; // instance to serialize
serialize(<archive>, foo);

contestado el 17 de mayo de 11 a las 02:05

No hay formas de inferir nombres de miembros en plantillas. Deberá especificar todo explícitamente, así:

template<typename ObjT, typename MemberT, MemberT ObjT::*Ptr>
struct member{};

mpl::vector
<
    member<Object, string, &Object::a>,
    member<Object, int, &Object::b>,
    member<Object, long, &Object::c>,
    member<Object, char, &Object::d>
>;

Otra opción es crear funciones para ayudar a generar member, define un operator>> esperando member que los fusiona en un member_vec, Y un operator>> esperando member_vec que se fusiona en un mayor member_vec. Como solo está usando el tipo, el compilador puede optimizar cualquier llamada de función real

Las funciones pueden usar argumentos de plantilla implícitos, por lo que pueden hacer que los serializadores necesiten un poco menos de código para definir:

auto serializer =
        mem(&Object::a) >>
        mem(&Object::b) >>
        mem(&Object::c) >>
        mem(&Object::d);

Yo mismo hice serializadores, usando ambas técnicas. El segundo es con el que estoy más feliz.

contestado el 17 de mayo de 11 a las 00:05

Puedes usar mpl::string para representar los nombres de los miembros. En mi aplicación, hago un poco de generación de código que emite algo como lo siguiente.

typedef mpl::string < 'n', 'a', 'm', 'e' > name;

Puede utilizar el mpl::c_str < name >::value para obtener la representación de la cadena. es decir, "nombre".

Guardo una secuencia de dichos nombres de miembros, otra secuencia para punteros de miembros, los comprimo y luego uso uno de los algoritmos de consulta boost :: fusion para encontrar el puntero de miembro para un nombre de miembro dado.

Publicaré el código si estás interesado. Actualmente no tengo acceso a él ya que está en la PC de mi hogar.

Respondido el 03 de junio de 11 a las 19:06

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.