Advertisement
Guest User

Type Erasure Zig-Zag

a guest
Dec 15th, 2015
131
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.88 KB | None | 0 0
  1. #ifndef PROJECT_DEFINES
  2. #define PROJECT_DEFINES
  3.  
  4. #define EXTEND_NVI(class_name) \
  5.     virtual void class_name ## _save( StreamWrapper &out, const quint32 p_version = 0 ) = 0;\
  6.     virtual void class_name ## _load( StreamWrapper &in, const quint32 p_version = 0 ) = 0;
  7.  
  8. #endif // PROJECT_DEFINES
  9.  
  10.  
  11. #ifndef SERIALIZABLE_H
  12. #define SERIALIZABLE_H
  13.  
  14. #include <QObject>
  15. #include <QDataStream>
  16.  
  17. #include <boost/serialization/access.hpp>
  18. #include <boost/serialization/version.hpp>
  19. #include <boost/serialization/split_member.hpp>
  20.  
  21. #include "Utilities/project_defines.hpp"
  22.  
  23. #include "streamwrapper.h"
  24.  
  25. class Serializable : public QObject
  26. {
  27.     Q_OBJECT
  28.    
  29.     friend class boost::serialization::access;
  30.    
  31.     EXTEND_NVI( Serializable )
  32.    
  33.     quint32 m_ID;
  34.     quint16 m_version;
  35.  
  36.   protected:
  37.     quint32 ID() const;
  38.     void setID( const quint32 &ID );
  39.  
  40.     quint16 version() const;
  41.     void setVersion( const quint16 &version );
  42.    
  43.   public:
  44.     explicit Serializable( quint32 p_ID, QObject *parent = 0 ) : QObject( parent ),
  45.         m_ID( p_ID ) {}
  46.     virtual ~Serializable() {}
  47.  
  48.     BOOST_SERIALIZATION_SPLIT_MEMBER()
  49.    
  50.     template <typename Stream>
  51.     void save( Stream &out, const quint32 p_version = 0 )
  52.     {
  53.         StreamWrapper stream( out );
  54.         stream << m_ID << m_version;
  55.         Serializable_save( stream, p_version );
  56.     }
  57.    
  58.     template <typename Stream>
  59.     void load( Stream &in, const quint32 p_version = 0 )
  60.     {
  61.         StreamWrapper stream( in );
  62.         stream >> m_ID >> m_version;
  63.         Serializable_load( stream, p_version );
  64.     }
  65. };
  66.  
  67. template <class Archive>
  68. Archive &operator << ( Archive &out, const Serializable &module )
  69. {
  70.     module.save( out );
  71.     return out;
  72. }
  73.  
  74. template <class Archive>
  75. Archive &operator >> ( Archive &in, Serializable &module )
  76. {
  77.     module.load( in );
  78.     return in;
  79. }
  80.  
  81. #endif // SERIALIZABLE_H
  82.  
  83.  
  84. #ifndef STREAMWRAPPER_H
  85. #define STREAMWRAPPER_H
  86.  
  87. #include "streamholder.h"
  88.  
  89. class StreamWrapper
  90. {
  91.     Stream_I *m_stream_holder; // Smart pointers...?
  92.     Stream_I &m_stream; // Convenience of use.
  93.    
  94.   public:
  95.     template < typename Stream >
  96.     explicit StreamWrapper( Stream &p_stream ) : // Implicit creation gave me problems so for now I made the ctor explicit.
  97.         m_stream_holder( new StreamHolder<Stream>( p_stream ) ),
  98.         m_stream( *m_stream_holder )
  99.     {}
  100.    
  101.     inline StreamWrapper &operator <<( ModuleWrapper p_module ) { m_stream << p_module; return *this; }
  102.     inline StreamWrapper &operator >>( ModuleWrapper p_module ) { m_stream >> p_module; return *this; }
  103.    
  104.     ~StreamWrapper() { delete m_stream_holder; }
  105. };
  106.  
  107. #endif // STREAMWRAPPER_H
  108.  
  109.  
  110. #ifndef STREAM_I_H
  111. #define STREAM_I_H
  112.  
  113. #include "modulewrapper.h"
  114.  
  115. class Stream_I
  116. {
  117.   public:
  118.     Stream_I();
  119.     virtual ~Stream_I() {}
  120.    
  121.     virtual void operator << ( ModuleWrapper &p_module ) = 0;
  122.     virtual void operator >> ( ModuleWrapper &p_module ) = 0;
  123. };
  124.  
  125. #endif // STREAM_I_H
  126.  
  127.  
  128. #ifndef STREAMHOLDER_H
  129. #define STREAMHOLDER_H
  130.  
  131. #include "stream_i.h"
  132.  
  133. template <typename Stream>
  134. class StreamHolder : public Stream_I
  135. {
  136.     Stream &m_stream;
  137.    
  138.   public:
  139.     StreamHolder( Stream &p_stream ) : m_stream( p_stream ) {}
  140.    
  141.     // Note '<<' & '>>' reversal.
  142.     // The now-concrete stream type is sent to the module for it to send itself into the stream.
  143.     // Visitor pattern stuff.
  144.     inline virtual void operator << ( ModuleWrapper &p_module ) { p_module >> m_stream; }
  145.     inline virtual void operator >> ( ModuleWrapper &p_module ) { p_module << m_stream; }
  146. };
  147.  
  148. #endif // STREAMHOLDER_H
  149.  
  150.  
  151. #ifndef MODULEWRAPPER_H
  152. #define MODULEWRAPPER_H
  153.  
  154. #include "moduleholder.h"
  155.  
  156. class ModuleWrapper
  157. {
  158.     Module_I *m_module_holder;
  159.     Module_I &m_module; // Convenience of use.
  160.    
  161.   public:
  162.     template <typename Module>
  163.     ModuleWrapper( Module &p_module ) :
  164.         m_module_holder( new ModuleHolder<Module>( p_module ) ),
  165.         m_module( *m_module_holder )
  166.     {}
  167.    
  168.     // Fun fact: 'typename' and 'class' are synonymous in this context.
  169.     // http://stackoverflow.com/questions/213121/use-class-or-typename-for-template-parameters
  170.     // http://stackoverflow.com/questions/2023977/c-difference-of-keywords-typename-and-class-in-templates
  171.    
  172.     template <typename Stream>
  173.     inline void operator << ( Stream &p_stream ) { m_module << p_stream; }
  174.     template <class Stream>
  175.     inline void operator >> ( Stream &p_stream ) { m_module >> p_stream; }
  176.    
  177.     ~ModuleWrapper() { delete m_module_holder; }
  178. };
  179.  
  180. #endif // MODULEWRAPPER_H
  181.  
  182.  
  183. #ifndef MODULE_I_H
  184. #define MODULE_I_H
  185.  
  186. #include <QDataStream>
  187.  
  188. #include <boost/archive/text_iarchive.hpp>
  189. #include <boost/archive/text_oarchive.hpp>
  190.  
  191. class Module_I
  192. {
  193.   public:
  194.     Module_I();
  195.     virtual ~Module_I() {}
  196.    
  197.     // Here you have to give concrete types in order to get out of the generalization loop.
  198.  
  199.     // The module is the one activating '<<' or '>>'
  200.     // so the directions regarding text_iarchive/oarchive are correct.
  201.     inline virtual void operator <<( QDataStream p_stream ) = 0;
  202.     inline virtual void operator >>( QDataStream p_stream ) = 0;
  203.     inline virtual void operator <<( boost::archive::text_iarchive p_stream ) = 0;
  204.     inline virtual void operator >>( boost::archive::text_oarchive p_stream ) = 0;
  205. };
  206.  
  207. #endif // MODULE_I_H
  208.  
  209.  
  210. #ifndef MODULEHOLDER_H
  211. #define MODULEHOLDER_H
  212.  
  213. #include "module_i.h"
  214.  
  215. #include "qclassesserialization.h" // Define your ways of serializing QThings like this:
  216. //namespace boost
  217. //{
  218. //namespace serialization
  219. //{
  220. //// QString
  221. //template<class Archive>
  222. //void serialize( Archive &archive, QString &p_QString, const unsigned int file_version )
  223. //{
  224. //    split_free( archive, p_QString, file_version );
  225. //}
  226.  
  227. //template<class Archive>
  228. //void save( Archive &archive, const QString &p_QString, const unsigned int )
  229. //{
  230. //    std::string std_string = p_QString.toStdString();
  231. //    archive << BOOST_SERIALIZATION_NVP( std_string );
  232. //}
  233.  
  234. //template<class Archive>
  235. //void load( Archive &archive, QString &p_QString, const unsigned int )
  236. //{
  237. //    std::string std_string;
  238. //    archive >> BOOST_SERIALIZATION_NVP( std_string );
  239. //    p_QString = p_QString.fromStdString( std_string );
  240. //}
  241.  
  242. template <typename Module>
  243. class ModuleHolder : public Module_I
  244. {
  245.     Module &m_module;
  246.    
  247.   public:
  248.     ModuleHolder( Module p_module ) : m_module( p_module ) {}
  249.    
  250. // Finally, both types are concrete and the magic can happen.
  251.     inline virtual void operator <<( QDataStream p_stream ) { p_stream >> m_module; }
  252.     inline virtual void operator >>( QDataStream p_stream ) { p_stream << m_module; }
  253.     inline virtual void operator <<( boost::archive::text_iarchive p_stream ) { p_stream >> m_module; }
  254.     inline virtual void operator >>( boost::archive::text_oarchive p_stream ) { p_stream << m_module; }
  255. };
  256.  
  257. #endif // MODULEHOLDER_H
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement