← Back to team overview

yade-dev team mailing list archive

[Branch ~yade-dev/yade/trunk] Rev 2155: 1. Fix calling {pre, post}ProcessAttribute multiple times with boost::serialization.

 

------------------------------------------------------------
revno: 2155
committer: Václav Šmilauer <eudoxos@xxxxxxxx>
branch nick: trunk
timestamp: Mon 2010-04-19 14:50:54 +0200
message:
  1. Fix calling {pre,post}ProcessAttribute multiple times with boost::serialization.
added:
  extra/introspection/
  extra/introspection/README
  extra/introspection/boost/
  extra/introspection/boost/introspection/
  extra/introspection/boost/introspection/has_member_data.hpp
  extra/introspection/boost/introspection/has_member_function.hpp
  extra/introspection/boost/introspection/traits.hpp
  extra/introspection/libs/
  extra/introspection/libs/introspection/
  extra/introspection/libs/introspection/doc/
  extra/introspection/libs/introspection/example/
  extra/introspection/libs/introspection/example/Jamfile.v2
  extra/introspection/libs/introspection/example/has_member_data.cpp
  extra/introspection/libs/introspection/example/has_member_function.cpp
  extra/introspection/libs/introspection/test/
modified:
  SConstruct
  lib/serialization/Serializable.hpp


--
lp:yade
https://code.launchpad.net/~yade-dev/yade/trunk

Your team Yade developers is subscribed to branch lp:yade.
To unsubscribe from this branch go to https://code.launchpad.net/~yade-dev/yade/trunk/+edit-subscription
=== modified file 'SConstruct'
--- SConstruct	2010-04-19 10:18:42 +0000
+++ SConstruct	2010-04-19 12:50:54 +0000
@@ -568,6 +568,7 @@
 	if os.path.exists(boostDir+'/python'): os.remove(boostDir+'/python') # remove deprecated symlink from previous line that can break things if it is left there; remove this at some point in the future
 	mkSymlink(buildDir+'/include/yade-'+env['version']+'/indexing_suite','py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders')
 	mkSymlink(boostDir+'/math','extra/floating_point_utilities_v3/boost/math')
+	mkSymlink(boostDir+'/introspection','extra/introspection/boost/introspection')
 	#env.InstallAs(env['PREFIX']+'/include/yade-'+env['version']+'/boost/foreach.hpp',foreachTarget)
 	env.Default(env.Alias('install',['$PREFIX/bin','$PREFIX/lib'])) # build and install everything that should go to instDirs, which are $PREFIX/{bin,lib} (uses scons' Install)
 

=== added directory 'extra/introspection'
=== added file 'extra/introspection/README'
--- extra/introspection/README	1970-01-01 00:00:00 +0000
+++ extra/introspection/README	2010-04-19 12:50:54 +0000
@@ -0,0 +1,1 @@
+downloaded from http://www.boostpro.com/vault/index.php?action=downloadfile&filename=introspection.zip&directory=&PHPSESSID=6d7ef3a7eaa1b601dbb852e571f09be7

=== added directory 'extra/introspection/boost'
=== added directory 'extra/introspection/boost/introspection'
=== added file 'extra/introspection/boost/introspection/has_member_data.hpp'
--- extra/introspection/boost/introspection/has_member_data.hpp	1970-01-01 00:00:00 +0000
+++ extra/introspection/boost/introspection/has_member_data.hpp	2010-04-19 12:50:54 +0000
@@ -0,0 +1,44 @@
+#ifndef __BOOS_INTROSPECTION__HAS_MEMBER_DATA_HPP__INCLUDED
+#define __BOOS_INTROSPECTION__HAS_MEMBER_DATA_HPP__INCLUDED
+
+#include <boost/mpl/bool.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/introspection/traits.hpp>
+
+////////////////////////////////////////////////////////////////////////////////
+// Generate a traits class that detect if a given type X has a member data
+// named Name of type Type. This class can only detects public member data or
+// member data that have been explicitly registered as 'traits visible' by the
+// BOOST_INTROSPECTION_SUPPORT macro.
+////////////////////////////////////////////////////////////////////////////////
+#define BOOST_HAS_MEMBER_DATA(Type,Name)                                \
+namespace boost                                                         \
+{                                                                       \
+  namespace introspection                                               \
+  {                                                                     \
+    template<class T> struct BOOST_PP_CAT(has_member_data_,Name)        \
+    {                                                                   \
+      typedef char NotFound;                                            \
+      struct Found { char x[2]; };                                      \
+                                                                        \
+      template< class X, Type X::*> struct member {};                   \
+                                                                        \
+      template<class X> static Found test(member<X,&X::Name>*);         \
+      template<class X> static NotFound test( ... );                    \
+                                                                        \
+      static const bool value  = (sizeof(Found) == sizeof(test<T>(0))); \
+      typedef mpl::bool_<value> type;                                   \
+    };                                                                  \
+  }                                                                     \
+}                                                                       \
+/**/
+
+////////////////////////////////////////////////////////////////////////////////
+// Used in a class, make the member data Name visible by the boost::introspection
+// traits class.
+////////////////////////////////////////////////////////////////////////////////
+#define BOOST_INTROSPECTION_SUPPORT(Class,Name)                              \
+friend class boost::introspection::BOOST_PP_CAT(has_member_data_,Name)<Class>\
+/**/
+
+#endif

=== added file 'extra/introspection/boost/introspection/has_member_function.hpp'
--- extra/introspection/boost/introspection/has_member_function.hpp	1970-01-01 00:00:00 +0000
+++ extra/introspection/boost/introspection/has_member_function.hpp	2010-04-19 12:50:54 +0000
@@ -0,0 +1,87 @@
+#ifndef __BOOS_INTROSPECTION__HAS_MEMBER_FUNCTION_HPP__INCLUDED
+#define __BOOS_INTROSPECTION__HAS_MEMBER_FUNCTION_HPP__INCLUDED
+
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/or.hpp>
+#include <boost/preprocessor/cat.hpp>
+#include <boost/introspection/traits.hpp>
+
+////////////////////////////////////////////////////////////////////////////////
+// Generate a traits class that detect if a given type X has a non-const member
+// function named Name with a given signature Sig.
+////////////////////////////////////////////////////////////////////////////////
+#define BOOST_HAS_NON_CONST_MEMBER_FUNCTION(Name,Sig)                   \
+namespace boost                                                         \
+{                                                                       \
+  namespace introspection                                               \
+  {                                                                     \
+    template<class T>                                                   \
+    struct BOOST_PP_CAT(has_non_const_member_function_,Name)            \
+    {                                                                   \
+      typedef char NotFound;                                            \
+      struct Found { char x[2]; };                                      \
+                                                                        \
+      template< class X                                                 \
+              , typename build_member_type<X,Sig>::type                 \
+              > struct member {};                                       \
+                                                                        \
+      template<class X> static Found test(member<X,&X::Name>*);         \
+      template<class X> static NotFound test( ... );                    \
+                                                                        \
+      static const bool value  = (sizeof(Found) == sizeof(test<T>(0))); \
+      typedef mpl::bool_<value> type;                                   \
+    };                                                                  \
+  }                                                                     \
+}                                                                       \
+/**/
+
+////////////////////////////////////////////////////////////////////////////////
+// Generate a traits class that detect if a given type X has a const member
+// function named Name with a given signature Sig.
+////////////////////////////////////////////////////////////////////////////////
+#define BOOST_HAS_CONST_MEMBER_FUNCTION(Name,Sig)                       \
+namespace boost                                                         \
+{                                                                       \
+  namespace introspection                                               \
+  {                                                                     \
+    template<class T>                                                   \
+    struct BOOST_PP_CAT(has_const_member_function_,Name)                \
+    {                                                                   \
+      typedef char NotFound;                                            \
+      struct Found { char x[2]; };                                      \
+                                                                        \
+      template< class X                                                 \
+              , typename build_const_member_type<X,Sig>::type           \
+              > struct member {};                                       \
+                                                                        \
+      template<class X> static Found test(member<X,&X::Name>*);         \
+      template<class X> static NotFound test( ... );                    \
+                                                                        \
+      static const bool value  = (sizeof(Found) == sizeof(test<T>(0))); \
+      typedef mpl::bool_<value> type;                                   \
+    };                                                                  \
+  }                                                                     \
+}
+/**/
+
+////////////////////////////////////////////////////////////////////////////////
+// Generate a traits class that detect if a given type X has a member function
+// named Name with a given signature Sig which is either const or non-const
+////////////////////////////////////////////////////////////////////////////////
+#define BOOST_HAS_MEMBER_FUNCTION(Name,Sig)                                 \
+BOOST_HAS_CONST_MEMBER_FUNCTION(Name,Sig)                                   \
+BOOST_HAS_NON_CONST_MEMBER_FUNCTION(Name,Sig)                               \
+                                                                            \
+namespace boost                                                             \
+{                                                                           \
+  namespace introspection                                                   \
+  {                                                                         \
+    template<class T>                                                       \
+    struct BOOST_PP_CAT(has_member_function_,Name) :                        \
+            mpl::or_< BOOST_PP_CAT(has_const_member_function_,Name)<T>      \
+                    , BOOST_PP_CAT(has_non_const_member_function_,Name)<T>  \
+                    > {};                                                   \
+  }                                                                         \
+}                                                                           \
+/**/
+#endif

=== added file 'extra/introspection/boost/introspection/traits.hpp'
--- extra/introspection/boost/introspection/traits.hpp	1970-01-01 00:00:00 +0000
+++ extra/introspection/boost/introspection/traits.hpp	2010-04-19 12:50:54 +0000
@@ -0,0 +1,50 @@
+#ifndef __BOOS_INTROSPECTION__TRAITS_HPP__INCLUDED
+#define __BOOS_INTROSPECTION__TRAITS_HPP__INCLUDED
+
+#include <boost/function_types/result_type.hpp>
+#include <boost/function_types/parameter_types.hpp>
+#include <boost/function_types/member_function_pointer.hpp>
+#include <boost/function_types/property_tags.hpp>
+
+namespace boost
+{
+  namespace introspection
+  {
+    ////////////////////////////////////////////////////////////////////////////
+    // Build a MPL sequence correspondign to the components of a member function
+    // type of class X with signature similar to Prototype.
+    // E.g :
+    // function_to_member<foo, void(int,long)>::type => <void,foo*,int,long>
+    //
+    ////////////////////////////////////////////////////////////////////////////
+    template<class X, class Prototype> struct function_to_member
+    {
+      typedef typename function_types::result_type<Prototype>::type     result;
+      typedef typename function_types::parameter_types<Prototype>::type args;
+      typedef typename mpl::push_front<args,X*>::type                   base;
+      typedef typename mpl::push_front<base,result>::type               type;
+    };
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Turn a class and a function type into a member function pointer with the
+    // same signature.
+    ////////////////////////////////////////////////////////////////////////////
+    template<class X, class Prototype> struct build_member_type
+    {
+      typedef typename function_to_member<X,Prototype>::type                root;
+      typedef typename function_types::member_function_pointer<root>::type  type;
+    };
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Turn a class and a function type into a const member function pointer
+    // with the same signature.
+    ////////////////////////////////////////////////////////////////////////////
+    template<class X, class Prototype> struct build_const_member_type
+    {
+      typedef typename function_to_member<X,Prototype>::type               root;
+      typedef typename function_types::member_function_pointer<root,function_types::const_qualified>::type type;
+    };
+  }
+}
+
+#endif

=== added directory 'extra/introspection/libs'
=== added directory 'extra/introspection/libs/introspection'
=== added directory 'extra/introspection/libs/introspection/doc'
=== added directory 'extra/introspection/libs/introspection/example'
=== added file 'extra/introspection/libs/introspection/example/Jamfile.v2'
--- extra/introspection/libs/introspection/example/Jamfile.v2	1970-01-01 00:00:00 +0000
+++ extra/introspection/libs/introspection/example/Jamfile.v2	2010-04-19 12:50:54 +0000
@@ -0,0 +1,13 @@
+# (C) Copyright 2008: Joel Falcou
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+exe has_member_data
+    :
+       has_member_data.cpp
+    ;
+
+exe has_member_function
+    :
+        has_member_function.cpp
+    ;

=== added file 'extra/introspection/libs/introspection/example/has_member_data.cpp'
--- extra/introspection/libs/introspection/example/has_member_data.cpp	1970-01-01 00:00:00 +0000
+++ extra/introspection/libs/introspection/example/has_member_data.cpp	2010-04-19 12:50:54 +0000
@@ -0,0 +1,29 @@
+
+#include <string>
+#include <boost/introspection/has_member_data.hpp>
+
+using namespace boost::introspection;
+
+BOOST_HAS_MEMBER_DATA(volatile int,value)
+
+struct foo
+{
+  int value;
+};
+
+struct bar
+{
+  BOOST_INTROSPECTION_SUPPORT(bar,value);
+
+  private:
+  volatile int value;
+};
+
+
+int main()
+{
+  BOOST_MPL_ASSERT(( has_member_data_value<foo> ));
+  BOOST_MPL_ASSERT(( has_member_data_value<bar> ));
+  BOOST_MPL_ASSERT_NOT(( has_member_data_value<std::string> ));
+  return 0;
+}

=== added file 'extra/introspection/libs/introspection/example/has_member_function.cpp'
--- extra/introspection/libs/introspection/example/has_member_function.cpp	1970-01-01 00:00:00 +0000
+++ extra/introspection/libs/introspection/example/has_member_function.cpp	2010-04-19 12:50:54 +0000
@@ -0,0 +1,46 @@
+#include <string>
+#include <vector>
+#include <boost/introspection/has_member_function.hpp>
+
+using namespace boost::introspection;
+
+struct foo
+{
+  void go();
+  char& done(long**,long**);
+};
+
+struct bar
+{
+  void go() const;
+  size_t size() const;
+};
+
+BOOST_HAS_MEMBER_FUNCTION(go,void());
+BOOST_HAS_CONST_MEMBER_FUNCTION(size,size_t());
+BOOST_HAS_NON_CONST_MEMBER_FUNCTION(done,char& (long**,long**));
+
+int main()
+{
+  // BOOST_HAS_MEMBER_FUNCTION enables check for both
+  // const and non-const member functions
+  BOOST_MPL_ASSERT(( has_non_const_member_function_go<foo> ));
+  BOOST_MPL_ASSERT_NOT(( has_non_const_member_function_go<bar> ));
+  BOOST_MPL_ASSERT_NOT(( has_non_const_member_function_go<std::string> ));
+
+  BOOST_MPL_ASSERT_NOT(( has_const_member_function_go<foo> ));
+  BOOST_MPL_ASSERT(( has_const_member_function_go<bar> ));
+  BOOST_MPL_ASSERT_NOT(( has_onst_member_function_go<std::string> ));
+
+  // BOOST_HAS_CONST_MEMBER_FUNCTION enables check for const member functions only
+  BOOST_MPL_ASSERT_NOT(( has_const_member_function_size<foo> ));
+  BOOST_MPL_ASSERT(( has_const_member_function_size<bar> ));
+  BOOST_MPL_ASSERT(( has_const_member_function_size<std::string> ));
+
+  // BOOST_HAS_NON_CONST_MEMBER_FUNCTION enables check for non-const member functions only
+  BOOST_MPL_ASSERT(( has_non_const_member_function_done<foo> ));
+  BOOST_MPL_ASSERT_NOT(( has_non_const_member_function_done<bar> ));
+  BOOST_MPL_ASSERT_NOT(( has_non_const_member_function_done<std::string> ));
+
+  return 0;
+}

=== added directory 'extra/introspection/libs/introspection/test'
=== modified file 'lib/serialization/Serializable.hpp'
--- lib/serialization/Serializable.hpp	2010-04-19 10:18:42 +0000
+++ lib/serialization/Serializable.hpp	2010-04-19 12:50:54 +0000
@@ -36,6 +36,9 @@
 
 #include<yade/lib-base/Math.hpp>
 
+// local copy
+#include<boost/introspection/has_member_function.hpp>
+
 
 using namespace boost;
 using namespace std;
@@ -61,7 +64,14 @@
 	// #define YADE_SERIALIZE_USING_BOOST
 	#define _REGISTER_BOOST_ATTRIBUTES_REPEAT(x,y,z) ar & BOOST_SERIALIZATION_NVP(z);
 	#define _REGISTER_BOOST_ATTRIBUTES(baseClass,attrs) \
-		friend class boost::serialization::access; private: template<class ArchiveT> void serialize(ArchiveT & ar, unsigned int version){ ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(baseClass); preProcessAttributes(ArchiveT::is_loading::value); BOOST_PP_SEQ_FOR_EACH(_REGISTER_BOOST_ATTRIBUTES_REPEAT,~,attrs) postProcessAttributes(ArchiveT::is_loading::value); }
+		friend class boost::serialization::access; \
+		private: template<class ArchiveT> void serialize(ArchiveT & ar, unsigned int version){ \
+			ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(baseClass);  \
+			/* will not work if preProcessAttributes is not virtual (it will not be called, but will be compile-time error, since this->preProcessAttributes will be undefined */ \
+			if(boost::introspection::has_non_const_member_function_preProcessAttributes<typeof(*this)>::value) this->preProcessAttributes(ArchiveT::is_loading::value); \
+			BOOST_PP_SEQ_FOR_EACH(_REGISTER_BOOST_ATTRIBUTES_REPEAT,~,attrs) \
+			if(boost::introspection::has_non_const_member_function_postProcessAttributes<typeof(*this)>::value) this->postProcessAttributes(ArchiveT::is_loading::value); \
+		}
 #else
 	#define _REGISTER_BOOST_ATTRIBUTES(baseClass,attrs)
 #endif
@@ -288,7 +298,13 @@
 	return inst;
 }
 
-
+// support templates for boost::introspection::has_member_function
+// signature bool(bool) MUST match actual functions (i.e. returning bool, taking bool as parameter)
+// creates boost::introspection::has_non_const_member_function_preProcessAttributes<class>
+// which is used to detect that method in serialization code (if using boost::serialization)
+// inside attribute registration macros above
+BOOST_HAS_NON_CONST_MEMBER_FUNCTION(preProcessAttributes,bool(bool))
+BOOST_HAS_NON_CONST_MEMBER_FUNCTION(postProcessAttributes,bool(bool))
 
 class Serializable : public Factorable
 {