Savarese Software Research Corporation

wisp_struct.h

Go to the documentation of this file.
00001 /*
00002  * Copyright 2006-2008 Savarese Software Research Corporation
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.savarese.com/software/ApacheLicense-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00022 #ifndef __SSRC_WISP_UTILITY_WISP_STRUCT_H
00023 #define __SSRC_WISP_UTILITY_WISP_STRUCT_H
00024 
00025 #include <boost/preprocessor/punctuation/comma_if.hpp>
00026 #include <boost/preprocessor/control/expr_iif.hpp>
00027 #include <boost/preprocessor/comparison/equal.hpp>
00028 #include <boost/preprocessor/comparison/less_equal.hpp>
00029 #include <boost/preprocessor/comparison/greater_equal.hpp>
00030 #include <boost/preprocessor/seq.hpp>
00031 #include <boost/preprocessor/array/elem.hpp>
00032 #include <boost/preprocessor/array/push_front.hpp>
00033 #include <boost/preprocessor/stringize.hpp>
00034 #include <boost/call_traits.hpp>
00035 
00036 #include <ssrc/wisp-packages.h>
00037 
00038 __BEGIN_NS_SSRC_WISP_UTILITY
00039 
00040 // This is a marker type, from which all WISP_STRUCT's are derived,
00041 // to facilitate metaprogramming
00042 // (e.g., std::is_base_of<wisp_struct, derived_type>).
00043 struct wisp_struct {
00044   template<class Archive> void serialize(Archive & ar, const unsigned int) { }
00045 };
00046 
00047 __END_NS_SSRC_WISP_UTILITY
00048 
00049 #define __WISP_STRUCT_MEMBER(r, data, arg) \
00050     BOOST_PP_TUPLE_ELEM(2, 0, arg) BOOST_PP_TUPLE_ELEM(2, 1, arg);
00051 
00052 #define __WISP_STRUCT_DEFAULT_INIT_MEMBER(r, data, i, arg) \
00053   BOOST_PP_COMMA_IF(i) BOOST_PP_TUPLE_ELEM(2, 1, arg)()
00054 
00055 #define __WISP_STRUCT_INIT_MEMBER(r, data, i, arg) \
00056   BOOST_PP_COMMA_IF(i) BOOST_PP_TUPLE_ELEM(2, 1, arg)(BOOST_PP_TUPLE_ELEM(2, 1, arg))
00057 
00058 #define __WISP_STRUCT_PARAM(r, in_template, i, arg) \
00059   BOOST_PP_COMMA_IF(i) BOOST_PP_EXPR_IIF(in_template, typename) boost::call_traits<BOOST_PP_TUPLE_ELEM(2, 0, arg)>::param_type BOOST_PP_TUPLE_ELEM(2, 1, arg)
00060 
00061 #define __WISP_STRUCT_PARAM_INIT(r, init, i, arg) \
00062   BOOST_PP_COMMA_IF(i) BOOST_PP_EXPR_IIF(BOOST_PP_ARRAY_ELEM(0, init), typename) boost::call_traits<BOOST_PP_TUPLE_ELEM(2, 0, arg)>::param_type BOOST_PP_TUPLE_ELEM(2, 1, arg) BOOST_PP_EXPR_IIF(BOOST_PP_GREATER_EQUAL(i, BOOST_PP_ARRAY_ELEM(1, init)), = BOOST_PP_ARRAY_ELEM(BOOST_PP_SUB(BOOST_PP_ADD(i, 2), BOOST_PP_ARRAY_ELEM(1, init)), init))
00063 
00064 #define __WISP_STRUCT_SERIALIZE(r, data, arg) & BOOST_PP_TUPLE_ELEM(2, 1, arg)
00065 
00066 // Serialization
00067 #define __WISP_STRUCT_SERIALIZE_MEMBERS(members)                        \
00068   template<class Archive>                                               \
00069   void serialize(Archive & ar, const unsigned int) {                    \
00070     ar BOOST_PP_SEQ_FOR_EACH(__WISP_STRUCT_SERIALIZE, _, members);      \
00071   }                                                                     \
00072 
00073 // Equality
00074 #define __WISP_STRUCT_EQOP_TEST(r, data, i, arg) \
00075   BOOST_PP_EXPR_IF(i, &&) (o1.BOOST_PP_TUPLE_ELEM(2, 1, arg) == o2.BOOST_PP_TUPLE_ELEM(2, 1, arg))
00076 
00077 #define __WISP_STRUCT_EQOP(name, seq)                                  \
00078   friend bool operator==(const name & o1, const name & o2) {    \
00079     return (BOOST_PP_SEQ_FOR_EACH_I(__WISP_STRUCT_EQOP_TEST, _, seq)); \
00080   }
00081 
00082 // Member visitation.  Visitor object must implement
00083 //   Visitor & operator(const char * const key, const V & value)
00084 // or
00085 //   Visitor & operator(const string & key, const V & value)
00086 // (possibly templatized on V) for each type to be visited.
00087 // Non-const value arg versions can be implemented as well if the visitor
00088 // wants to modify the members.  Operators return *this to allow chaining.
00089 #define __WISP_STRUCT_VISIT_MEMBERS(r, v, arg)                          \
00090   (BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(2, 1, arg)), BOOST_PP_TUPLE_ELEM(2, 1, arg))
00091 
00092 // Swig doesn't understand rvalue references
00093 #ifndef SWIG
00094 #define __WISP_STRUCT_VISIT(members)                                    \
00095   template<typename Visitor>                                            \
00096   void visit(Visitor && visitor) {                                      \
00097     visitor BOOST_PP_SEQ_FOR_EACH(__WISP_STRUCT_VISIT_MEMBERS, visitor, members); \
00098   }                                                                     \
00099   template<typename Visitor>                                            \
00100   void visit(Visitor && visitor) const {                                \
00101     visitor BOOST_PP_SEQ_FOR_EACH(__WISP_STRUCT_VISIT_MEMBERS, visitor, members); \
00102   }
00103 #else
00104 #define __WISP_STRUCT_VISIT(members)
00105 #endif
00106 
00107 // We exclude the struct name { } container for the benefit of client
00108 // code that wants to define its own macros that add extra functionality 
00109 // to the generated structures.
00110 #define __WISP_STRUCT(in_template, name, members)                       \
00111   BOOST_PP_SEQ_FOR_EACH(__WISP_STRUCT_MEMBER, _, members)               \
00112   name() :                                                              \
00113   BOOST_PP_SEQ_FOR_EACH_I(__WISP_STRUCT_DEFAULT_INIT_MEMBER, _, members) { } \
00114   explicit name(BOOST_PP_SEQ_FOR_EACH_I(__WISP_STRUCT_PARAM, in_template, members)) : \
00115   BOOST_PP_SEQ_FOR_EACH_I(__WISP_STRUCT_INIT_MEMBER, _, members) { }    \
00116   __WISP_STRUCT_SERIALIZE_MEMBERS(members)                              \
00117   __WISP_STRUCT_EQOP(name, members)                                     \
00118   __WISP_STRUCT_VISIT(members)
00119 
00120 #define __WISP_STRUCT_WITH_INIT(in_template, name, members, initializers) \
00121   BOOST_PP_SEQ_FOR_EACH(__WISP_STRUCT_MEMBER, _, members)               \
00122   explicit name(BOOST_PP_SEQ_FOR_EACH_I(__WISP_STRUCT_PARAM_INIT, BOOST_PP_ARRAY_PUSH_FRONT(BOOST_PP_ARRAY_PUSH_FRONT(initializers, BOOST_PP_SUB(BOOST_PP_SEQ_SIZE(members), BOOST_PP_ARRAY_SIZE(initializers))), in_template), members)) : \
00123   BOOST_PP_SEQ_FOR_EACH_I(__WISP_STRUCT_INIT_MEMBER, _, members) { }    \
00124   __WISP_STRUCT_SERIALIZE_MEMBERS(members)                              \
00125   __WISP_STRUCT_EQOP(name, members)                                     \
00126   __WISP_STRUCT_VISIT(members)
00127 
00128 #define WISP_STRUCT(name, members)  \
00129   struct name : public NS_SSRC_WISP_UTILITY::wisp_struct { __WISP_STRUCT(0, name, members) }
00130 
00131 #define WISP_STRUCT_T(name, members) \
00132   struct name : public NS_SSRC_WISP_UTILITY::wisp_struct { __WISP_STRUCT(1, name, members) }
00133 
00134 #define WISP_STRUCT_WITH_INIT(name, members, initializers)    \
00135   struct name : public NS_SSRC_WISP_UTILITY::wisp_struct {  __WISP_STRUCT_WITH_INIT(0, name, members, BOOST_PP_SEQ_TO_ARRAY(initializers)) }
00136 
00137 #define WISP_STRUCT_WITH_INIT_T(name, members, initializers)    \
00138   struct name : public NS_SSRC_WISP_UTILITY::wisp_struct { __WISP_STRUCT_WITH_INIT(1, name, members, BOOST_PP_SEQ_TO_ARRAY(initializers)) }
00139 
00140 #endif

Savarese Software Research Corporation
Copyright © 2006-2010 Savarese Software Research Corporation. All rights reserved.