3

I am trying to get a serialization module for classes using boost fusion. I have converted my class to a boost::fusion sequence. This example is followed from the slides of the talk of Michael Caisse at boostcon 13

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

The example explained by Michael worked good for struct type. The same could not be applied for class types. What am i missing here ?

#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;
}
manlio
  • 18,345
  • 14
  • 76
  • 126
balas bellobas
  • 237
  • 3
  • 12
  • 1
    http://coliru.stacked-crooked.com/a/5f242fb421491591 – llonesmiz Apr 08 '14 at 18:30
  • http://coliru.stacked-crooked.com/a/6274cadeb079a3bd – balas bellobas Apr 08 '14 at 19:08
  • thanks for the link. if i were to use a class type composed of another class type. the code is broken for this case. how do we solve this case . – balas bellobas Apr 08 '14 at 19:09
  • 1
    I don't know if this is correct (I'm using trial and error), but [this](http://coliru.stacked-crooked.com/a/2749f8c124a2fa9c) seems to solve your immediate problem. – llonesmiz Apr 08 '14 at 21:07
  • http://coliru.stacked-crooked.com/a/61b16d2fc56cb72c – balas bellobas Apr 09 '14 at 01:41
  • Added a class containing a vector. Initial compilation resulted in a error. TODO: To solve this error and post the result to this forum for verification. Solution is to specialize serialize_out for containers. – balas bellobas Apr 09 '14 at 01:43
  • 1
    It seems that my initial approach of specializing for `adt_attribute_proxy` in `simple` was wrong (it was really far from simple). I think this [new approach](http://coliru.stacked-crooked.com/a/773d844d19aa57c7) (changing only `serial_out` without modifing `simple::serialize`) makes more sense (but I wouldn't count on it being correct either). – llonesmiz Apr 09 '14 at 06:51
  • http://coliru.stacked-crooked.com/a/6a2f313bf6f632c7 I am trying to do a de-serialization for class types. So what i understand is , we need to use the adaptor functions that invokes set_exprN of the adt_attribute_proxy class. – balas bellobas Apr 12 '14 at 17:48
  • http://coliru.stacked-crooked.com/a/b58022f4ec6ec4ea I'm even less sure that this is right. I have made the operator()'s in `serial_in` const (I think you can avoid this by using `serial_in in(ia);boost::fusion::for_each( v, in );`). Made the `adt_attribute_proxy` parameters also const. Changed one line in the loop that fills the vector. And the change I'm less confident about, changed the functions `get_x`, `get_y` and `get_sp` to return a reference (and changed the BOOST_FUSION_ADAPT_ADT invocations accordingly). This seems to work, hope it helps. – llonesmiz Apr 12 '14 at 19:22
  • I am of the feeling what is being done here is not correct. We are getting a reference to a class member variable and passing it to the de-serilize function that changes the value of the class member variable. So the crux here is using the proxyN.get() of the adt_attribute_proxy class. What i feel should be done is using the proxyN=t (assignment operator overload of the adt_attribute_proxy class). I was not sure how to invoke the assignment operator from the proxy class. – balas bellobas Apr 13 '14 at 06:00
  • http://www.boost.org/doc/libs/1_55_0/libs/fusion/doc/html/fusion/notes.html proxyN=t Invokes set_exprN, with t being an arbitrary object. set_exprN may access the variables named obj of type type_name&, which represent the corresponding instance of type_name, and val of an arbitrary const-qualified reference template type parameter Val, which represents t proxyN.get() Invokes get_exprN and forwards its return value. get_exprN may access the variable named obj of type type_name& which represents the underlying instance of type_name. attribute_typeN may specify the type that get_exprN denotes to – balas bellobas Apr 13 '14 at 06:02
  • 1
    I agree, I was trying to change the program in a similar way. [This](http://coliru.stacked-crooked.com/a/1fe37783bb484b1f) is what I got. Thanks for the link, I wasn't aware of that section of the documentation. – llonesmiz Apr 13 '14 at 06:20
  • Thanks for the quick response. I was getting lost in invoking the assignment operator for the class contained in the proxy class. – balas bellobas Apr 13 '14 at 06:23
  • I am trying a different approach to the same serialization problem. Got stuck when serializing a container of structs. Can you review and let me know what I am doing wrong. http://coliru.stacked-crooked.com/a/26bd646429b9880c – balas bellobas Apr 14 '14 at 15:59
  • 1
    You were assuming that whatever was in a list (or vector) was a POD. Changing `serialize_pod` with `simple_serializer` seems to solve that problem (You'll probably have the same problem with your loads, but I don't have time to test it). http://coliru.stacked-crooked.com/a/28a663f0787f8e09 . – llonesmiz Apr 14 '14 at 18:17

0 Answers0