yade-dev team mailing list archive
-
yade-dev team
-
Mailing list archive
-
Message #04034
[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
{