00001 #ifndef toast_typed_factory_hpp_INCLUDED
00002 #define toast_typed_factory_hpp_INCLUDED
00003
00004 #include <boost/shared_ptr.hpp>
00005 #include <boost/bind.hpp>
00006 #include <boost/function.hpp>
00007
00008 #include <boost/utility/typed_in_place_factory.hpp>
00009 #include <boost/preprocessor/cat.hpp>
00010 #include <boost/preprocessor/punctuation/paren.hpp>
00011 #include <boost/preprocessor/iteration/iterate.hpp>
00012 #include <boost/preprocessor/repetition/repeat.hpp>
00013 #include <boost/preprocessor/repetition/enum.hpp>
00014 #include <boost/preprocessor/repetition/enum_params.hpp>
00015 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
00016 #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
00017
00025 #ifndef TOAST_MAX_TYPED_FACTORY_ARITY
00026
00034 #define TOAST_MAX_TYPED_FACTORY_ARITY 10
00035
00036 #endif
00037
00039 #define TOAST_TYPED_FACTORY_INIT(z,n,_) BOOST_PP_CAT(m_a,n) BOOST_PP_LPAREN() BOOST_PP_CAT(a,n) BOOST_PP_RPAREN()
00040 #define TOAST_TYPED_FACTORY_DECL(z,n,_) BOOST_PP_CAT(A,n) BOOST_PP_CAT(m_a,n);
00041
00042 namespace toast {
00043 namespace detail {
00044 #define BOOST_PP_ITERATION_LIMITS (0, TOAST_MAX_TYPED_FACTORY_ARITY)
00045 #define BOOST_PP_FILENAME_1 <toast/detail/typed_factoryN.hpp>
00046 #include BOOST_PP_ITERATE()
00047 }
00049
00050
00080 template <typename T>
00081 class typed_factory : public boost::typed_in_place_factory_base
00082 {
00083 boost::shared_ptr< boost::function<void (void *)> > apply_;
00084 public:
00085 typedef T value_type;
00086
00091 T * create() const
00092 {
00093 void *p = operator new(sizeof(T));
00094 (*apply_)(p);
00095 return static_cast<T *>(p);
00096 }
00097
00103 void apply( void *addr ) const { (*apply_)(addr); }
00104
00105
00107 #define BOOST_PP_ITERATION_LIMITS (0, TOAST_MAX_TYPED_FACTORY_ARITY)
00108 #define BOOST_PP_FILENAME_1 <toast/typed_factory.hpp>
00109 #include BOOST_PP_ITERATE()
00111
00112 };
00113
00116 }
00117
00118
00119 #undef TOAST_TYPED_FACTORY_INIT
00120 #undef TOAST_TYPED_FACTORY_DECL
00121
00122 #elif BOOST_PP_IS_ITERATING
00123
00124 #define N BOOST_PP_ITERATION()
00125
00126 #if N > 0
00127 template <BOOST_PP_ENUM_PARAMS(N, typename A) >
00128 #endif
00129 typed_factory( BOOST_PP_ENUM_BINARY_PARAMS(N, A, a) )
00130 : apply_( new boost::function<void (void *)>(
00131 boost::bind(
00132 & BOOST_PP_CAT(detail::typed_factory, N)<T BOOST_PP_ENUM_TRAILING_PARAMS(N, A)>::apply,
00133 BOOST_PP_CAT(detail::typed_factory,N) <T BOOST_PP_ENUM_TRAILING_PARAMS(N, A)>( BOOST_PP_ENUM_PARAMS(N,a) ),
00134 _1
00135 )
00136 )
00137 ) {}
00138
00139
00140
00141 #if N > 0
00142 template <BOOST_PP_ENUM_PARAMS(N, typename A) >
00143 typed_factory( BOOST_PP_CAT(boost::typed_in_place_factory, N) <T BOOST_PP_ENUM_TRAILING_PARAMS(N,A)> const &f )
00144 : apply_( new boost::function<void (void *)>(
00145 boost::bind(
00146 & BOOST_PP_CAT(boost::typed_in_place_factory,N) <T BOOST_PP_ENUM_TRAILING_PARAMS(N,A)>::apply,
00147 f, _1 ) ) ) {}
00148 #endif
00149
00150 #undef N
00151
00152 #endif
00153