Повысить MPL для генерации кода для сериализации объектов? - PullRequest
3 голосов
/ 16 мая 2011

Я хочу сгенерировать код сериализации / десериализации для

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

глядя на последовательность mpl, но мне нужно иметь возможность идентифицировать объект и получить его обратно, я не могу понять, как мне получить имена его членов, я должен знать это

код должен выглядеть как

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

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

Я хочу сгенерировать приведенный выше код пользователем, определяющим только последовательность mpl, соответствующую макету объекта, это выполнимо, можете ли вы дать мне несколько советов?

Моя цель:

Пользователь определяет mpl::vector<String, int, long, char> для вышеуказанного объекта, и мой metaprogram может сгенерировать необходимый код.

Ответы [ 3 ]

10 голосов
/ 17 мая 2011

Рассмотрим boost::fusion и используйте макрос BOOST_FUSION_ADAPT_STRUCT() для перевода вашей структуры в последовательность слияния (произвольный доступ), например, как только вы определили структуру выше, вы можете сделать что-то вроде

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

Теперь, когда он был повышен, вы можете просто использовать for_each для перебора членов, что-то вроде:

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));
}

Чтобы использовать, это должно быть так просто, как:

Object foo; // instance to serialize
serialize(<archive>, foo);
2 голосов
/ 17 мая 2011

Нет способов определить имена членов в шаблонах. Вам нужно будет указать все явно, как это:

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>
>;

Другой вариант - создать функции, помогающие генерировать member, определить operator>> для member, который объединяет их в member_vec, и operator>> для member_vec, который объединяется в больший member_vec. Поскольку вы используете только тип, компилятор может оптимизировать любые реальные вызовы функций

Функции могут использовать неявные аргументы шаблона, поэтому сериализаторам требуется чуть меньше кода для определения:

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

Я сам сделал сериализаторы, используя обе техники. Второй - это то, чем я больше всего доволен.

0 голосов
/ 03 июня 2011

Вы можете использовать mpl::string для представления имен членов. В моем приложении я немного генерирую код, который выдает что-то вроде следующего.

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

Вы можете использовать mpl::c_str < name >::value, чтобы получить строковое представление. то есть "имя".

Я храню последовательность таких имен элементов, другую последовательность для указателей элементов, объединяю их в zip и затем использую один из алгоритмов запроса boost :: fusion, чтобы найти указатель элемента для данного имени элемента.

Я отправлю код, если вам интересно. В настоящее время у меня нет доступа к нему, поскольку он находится на моем домашнем компьютере.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...