Ускорьте сериализацию класса с помощью BOOST_FUSION_ADAPT_ADT.

Я пытаюсь получить модуль сериализации для классов, использующих ускоренное слияние. Я преобразовал свой класс в последовательность boost::fusion. Этот пример взят из слайдов выступления Майкла Кейса на boostcon 13.

https://github.com/boostcon/cppnow_presentations_2013/blob/master/thu/solving_world_problems_with_fusion.pdf?raw=true

Пример, объясненный Майклом, хорошо работал для типа структуры. То же самое нельзя было применить к типам классов. Что мне здесь не хватает?

#include <iostream>
#include <typeinfo>
#include <string>
#include <boost/fusion/include/sequence.hpp>
#include <boost/fusion/include/algorithm.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/adapt_adt.hpp>
#include <boost/fusion/include/is_sequence.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/type_traits.hpp> 

#include <vector>
#include <list>

using namespace std;

template< typename T >
void serialize(T v)
{
boost::fusion::for_each( v, (serial_out()) );
}

struct serial_out
{
template< typename T > 
void operator() ( T & v , typename std::enable_if<!boost::fusion::traits::is_sequence<T>::value>::type* = 0 ) const
{ 
    simple::serialize<T>::write(v); 
}

template< typename T > 
void operator() ( T & v , typename std::enable_if<boost::fusion::traits::is_sequence<T>::value>::type* = 0  ) const
{ 
    serialize(v); 
}

template< typename T >
void operator()( std::vector<T> & v ) const
{
    simple::serialize<int>::write(v.size());
    std::for_each(v.begin(),v.end(),*this);
}

template< typename T >
void operator()( std::list<T> & v ) const
{
    simple::serialize<int>::write(v.size());
    std::for_each(v.begin(),v.end(),*this);
}
};

namespace simple
{
template<typename T> struct serialize{};
template<> struct serialize<int>
{
    static void write(int v) { cout << v << endl; }
};
template<> struct serialize<float>
{
    static void write(float v) { cout << v << endl;  }
};
template<> struct serialize<std::string>
{
    static void write(std::string v)
    {
        cout << v << endl; 
    }
};
}


class secret_point
{
public:
secret_point(double x, double y) : x_(x), y_(y) {}
double get_x() const { return x_; }
void set_x(double d) { x_=d; }
double get_y() const { return y_; }
void set_y(double d) { y_=d; }
private:
double x_, y_;
};

BOOST_FUSION_ADAPT_ADT( secret_point, (double, double, obj.get_x(), obj.set_x(val) ) (double, double, obj.get_y(), obj.set_y(val) ) )

int main(int argc, char *argv[]) 
{
secret_point p(112,233);
serialize(p);

return 0;
}

person balas bellobas    schedule 08.04.2014    source источник
comment
coliru.stacked-crooked.com/a/5f242fb421491591   -  person llonesmiz    schedule 08.04.2014
comment
coliru.stacked-crooked.com/a/6274cadeb079a3bd   -  person balas bellobas    schedule 08.04.2014
comment
спасибо за ссылку. если бы я использовал тип класса, состоящий из другого типа класса. код сломан для этого случая. как мы решим это дело.   -  person balas bellobas    schedule 08.04.2014
comment
Я не знаю, правильно ли это (использую метод проб и ошибок), но это, кажется, решает вашу насущную проблему.   -  person llonesmiz    schedule 09.04.2014
comment
coliru.stacked-crooked.com/a/61b16d2fc56cb72c   -  person balas bellobas    schedule 09.04.2014
comment
Добавлен класс, содержащий вектор. Первоначальная компиляция привела к ошибке. TODO: решить эту ошибку и опубликовать результат на этом форуме для проверки. Решение состоит в том, чтобы специализировать serialize_out для контейнеров.   -  person balas bellobas    schedule 09.04.2014
comment
Кажется, что мой первоначальный подход к специализации adt_attribute_proxy в simple был неправильным (это было действительно далеко не просто). Я думаю, что этот новый подход (изменение только serial_out без изменения simple::serialize) имеет больше смысла (но Я бы тоже не рассчитывал, что это правильно).   -  person llonesmiz    schedule 09.04.2014
comment
Мне нравится это решение. Спасибо   -  person balas bellobas    schedule 09.04.2014
comment
coliru.stacked-crooked.com/a/6a2f313bf6f632c7 Я пытаюсь выполнить -сериализация для типов классов. Насколько я понимаю, нам нужно использовать функции адаптера, которые вызывают set_exprN класса adt_attribute_proxy.   -  person balas bellobas    schedule 12.04.2014
comment
coliru.stacked-crooked.com/a/b58022f4ec6ec4ea Я еще менее уверен, что это правильно. Я сделал операторы () в serial_in const (я думаю, вы можете избежать этого, используя serial_in in(ia);boost::fusion::for_each( v, in );). Сделал параметры adt_attribute_proxy также постоянными. Изменена одна строка в цикле, который заполняет вектор. И изменение, в котором я менее уверен, изменило функции get_x, get_y и get_sp, чтобы они возвращали ссылку (и соответственно изменили вызовы BOOST_FUSION_ADAPT_ADT). Кажется, это работает, надеюсь, это поможет.   -  person llonesmiz    schedule 12.04.2014
comment
Я чувствую, что то, что здесь делается, неправильно. Мы получаем ссылку на переменную-член класса и передаем ее функции десериализации, которая изменяет значение переменной-члена класса. Итак, суть здесь в использовании proxyN.get() класса adt_attribute_proxy. Я считаю, что нужно использовать proxyN=t (перегрузка оператора присваивания класса adt_attribute_proxy). Я не знал, как вызвать оператор присваивания из прокси-класса.   -  person balas bellobas    schedule 13.04.2014
comment
boost.org/doc/libs/ 1_55_0/libs/fusion/doc/html/fusion/ proxyN=t Вызывает set_exprN, где t является произвольным объектом. set_exprN может обращаться к переменным с именем obj типа type_name&, которые представляют соответствующий экземпляр type_name, и val произвольного параметра типа ссылочного шаблона с уточнением const Val, который представляет t proxyN.get() Вызывает get_exprN и пересылает его возвращаемое значение. get_exprN может получить доступ к переменной с именем obj типа type_name&, которая представляет базовый экземпляр type_name. attribute_typeN может указывать тип, который get_exprN обозначает для   -  person balas bellobas    schedule 13.04.2014
comment
Согласен, пробовал менять программу подобным образом. Вот что я получил. Спасибо за ссылку, я не знал об этом разделе документации.   -  person llonesmiz    schedule 13.04.2014
comment
Спасибо за быстрый ответ. Я терялся, вызывая оператор присваивания для класса, содержащегося в прокси-классе.   -  person balas bellobas    schedule 13.04.2014
comment
Я пробую другой подход к той же проблеме сериализации. Застрял при сериализации контейнера структур. Можете ли вы просмотреть и сообщить мне, что я делаю неправильно. coliru.stacked-crooked.com/a/26bd646429b9880c   -  person balas bellobas    schedule 14.04.2014
comment
Вы предполагали, что все, что было в списке (или векторе), было POD. Замена serialize_pod на simple_serializer, кажется, решает эту проблему (вероятно, у вас будет такая же проблема с вашими нагрузками, но у меня нет времени ее тестировать). coliru.stacked-crooked.com/a/28a663f0787f8e09 .   -  person llonesmiz    schedule 14.04.2014
comment
Хорошо поймал. Спасибо еще раз .   -  person balas bellobas    schedule 15.04.2014