/*////////////////////////////////////////////////////////////////////////////// // CMT Cosmic Muon Tomography project ////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// Copyright (c) 2014, Universita' degli Studi di Padova, INFN sez. di Padova All rights reserved Authors: Andrea Rigoni Garola < andrea.rigoni@pd.infn.it > ------------------------------------------------------------------ This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. //////////////////////////////////////////////////////////////////////////////*/ #ifndef U_OBJECTPROPS_H #define U_OBJECTPROPS_H #include #include #include //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // MACROS // #define ULIB_props() \ public: struct ObjectProps; \ virtual void init_properties(); \ inline struct ObjectProps &p() { /* static const unsigned int offset = props_offset(this); */ \ /* NON FUNZIA! return * (struct ObjectProps *)(reinterpret_cast(props())+offset); */ \ return *props()->ptr(); } \ typedef uLib::mpl::bool_::type propable_trait; \ public: struct DLL_PUBLIC ObjectProps #define properties() ULIB_props() #define default(vlaue) #define $$ p() #define $(_name) props_ref<_name>() #define $_init() \ if(props(this)) return; \ props_new(this); \ uLib::detail::ObjectProps::initializer::init_object_baselist(this); //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// namespace boost { namespace serialization { class access; } } namespace uLib { namespace detail { struct ObjectProps { /** Define a trait has_member to find if an Object is Propable*/ BOOST_MPL_HAS_XXX_TRAIT_DEF(propable_trait) /** IsA ProbapleObject Implementation Template */ template struct IsA : has_propable_trait {}; /** Lambda to get Props member type */ template struct props_type { typedef typename T::ObjectProps type; }; template struct get_props { /** CFList has result but this method check for has BaseList */ typedef typename detail::TypeIntrospection::child_first::type CFTypeList; /** Filter List items that have not Propable feature */ typedef typename mpl::filter_view< CFTypeList, IsA >::type FilteredCFTypeList; /** Get Props from each Parent in Seq */ typedef typename mpl::transform_view< FilteredCFTypeList, props_type >::type type; // qui sotto ho un problema che ho temporaneamente tamponato // // ovvero ho usato child_first_impl per ottenere la lista delle basi // // vorrei farlo facendo un pop_back ma non va forse perche il tipo // // non e' corretto. // /** Get Parent list from CFTypeList */ typedef typename detail::TypeIntrospection::child_first_impl::Childs CFBaseList; /** Filter Parents that have not Propable feature */ typedef typename mpl::filter_view< CFBaseList, IsA >::type FilteredCFBaseList; }; // TODO: convert to pp const value, // (non so se sia possibile con il dinamic casting intanto funziona cosi' ) template static unsigned int measure_offset(T1 base, T2 derived) { return reinterpret_cast(derived) - reinterpret_cast(base); } struct initializer { template struct lambda_init_object { _ObjectT *o; lambda_init_object(_ObjectT *o) : o(o) {} template void operator()(T) { o->T::init_properties(); } }; /** * This calls the internal init_properties() virtual function for each * object parent defined in BaseList only if it is propable */ template static void init_object_baselist(T *o) { typedef typename uLib::detail::ObjectProps::get_props::FilteredCFBaseList CFBaseList; mpl::for_each(lambda_init_object(o)); } /** * This calls the internal init_properties() virtual function only if * object is propable ( implementation if not propable ) */ template static typename boost::enable_if >,void>::type init_object(T *o) { ; // do nothing // } /** * This calls the internal init_properties() virtual function only if * object is propable ( implementation if propable ) */ template static typename boost::enable_if,void>::type init_object(T *o) { o->init_properties(); } }; template struct serialize_baselist { ThisClass & m_object; Archive & m_ar; serialize_baselist(ThisClass &o, Archive &ar) : m_object(o), m_ar(ar) {} template void operator()(T &o) { // T is taken fron get_props::FilteredPList types to get // type_info_name that is the type name defined by Type macro typedef typename props_type::type PType; std::string name(TypeIntrospection::access::type_info::name); boost::algorithm::replace_all(name,"::","_"); m_ar & boost::serialization::make_nvp( name.c_str() , boost::serialization::base_object(m_object)); } }; }; } // detail struct ObjectPropsBase { virtual ~ObjectPropsBase() {} virtual ObjectPropsBase *copy() = 0; template inline T *ptr() { return dynamic_cast(this); } template void serialize(ArchiveT &ar, const unsigned int version) {} }; template struct ObjectPropsImpl : ObjectPropsBase, ULIB_MPL_INHERIT_NOFOLD_SEQ(typename uLib::detail::ObjectProps::get_props::type) { typedef ObjectPropsImpl ThisClass; typedef typename uLib::detail::ObjectProps::get_props::type CFList; typedef typename uLib::detail::ObjectProps::get_props::FilteredCFTypeList FilteredCFTypeList; ObjectPropsBase *copy() { return new ThisClass(*this); } template void serialize(ArchiveT &ar, const unsigned int version) { boost::serialization::void_cast_register(); mpl::for_each(detail::ObjectProps::serialize_baselist(*this,ar)); } }; class ObjectPropable { ObjectPropsBase *m_props; friend class uLib::detail::ObjectProps; friend class boost::serialization::access; public: ObjectPropable() : m_props(NULL) {} ObjectPropable(const ObjectPropable &c) { if(c.m_props) m_props = c.m_props->copy(); else m_props = NULL; } ~ObjectPropable() { if(m_props) delete m_props; } template inline typename T::ObjectProps& props_ref() const { if(m_props) return *m_props->ptr(); else exit(1); } template inline typename T::ObjectProps* props(T *ptr = NULL) const { if(m_props) return m_props->ptr(); else return NULL; } protected: ObjectPropsBase *props() const { return m_props; } template inline void props_new(T* ptr = NULL) { if(!m_props) m_props = new ObjectPropsImpl; } /** NOT working dynamic cache casting */ template inline unsigned int props_offset(T *ptr) const { if(m_props) return detail::ObjectProps::measure_offset(m_props,m_props->ptr()); else return -1; } template void serialize(ArchiveT &ar, const unsigned int version) { if(m_props) ar & boost::serialization::make_nvp("properties",m_props); } public: /** * ObjectPropable is not directly propable itself to prevent Basclass * duplication in inherit_nofold. And for the same reason ANY VIRTUAL BASE * SHOULD NOT BE PROPABLE */ virtual void init_properties() {} }; } // uLib #endif // U_OBJECTPROPS_H