00001
00002
00003
00004
00005
00006
00007
00008 #ifndef BOOSTER_FUNCTION_H
00009 #define BOOSTER_FUNCTION_H
00010
00011 #include <booster/backtrace.h>
00012 #include <booster/clone_ptr.h>
00013
00014 namespace booster {
00015 template<typename Type>
00016 class function;
00017
00022 class bad_function_call : public booster::runtime_error {
00023 public:
00024 bad_function_call() :
00025 booster::runtime_error("bad_function_call")
00026 {
00027 }
00028 };
00029
00030
00031 #ifdef BOOSTER_DOXYGEN_DOCS
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 template<typename Result,typename ...Params>
00050 class function<Result(Params...)>
00051 {
00052 public:
00056 typedef Result result_type;
00060 function();
00065 template<typename F>
00066 function(F func);
00067
00071 function(function const &other);
00072
00077 template<typename F>
00078 function const &operator=(F func);
00079
00083 function const &operator=(function const &other);
00084
00088 result_type operator()(Params... params) const;
00092 bool empty() const;
00096 operator bool() const;
00097
00101 void swap(function &other);
00102 };
00103
00104 #else
00105
00106 #define BOOSTER_FUNCTION \
00107 template<typename Result BOOSTER_TEMPLATE_PARAMS > \
00108 class function<Result(BOOSTER_TEMPLATE_TYPE_PARAMS)> \
00109 { \
00110 public: \
00111 typedef Result result_type; \
00112 struct callable { \
00113 virtual Result call(BOOSTER_TYPE_PARAMS) =0; \
00114 virtual callable *clone() const = 0; \
00115 virtual ~callable(){} \
00116 }; \
00117 \
00118 template<typename R,typename F> \
00119 struct callable_impl : public callable { \
00120 F func; \
00121 callable_impl(F f) : func(f){} \
00122 virtual R call(BOOSTER_TYPE_PARAMS) \
00123 { return func(BOOSTER_CALL_PARAMS); } \
00124 virtual callable *clone() const \
00125 { return new callable_impl<R,F>(func); } \
00126 }; \
00127 template<typename F> \
00128 struct callable_impl<void,F> : public callable { \
00129 F func; \
00130 callable_impl(F f) : func(f){} \
00131 virtual void call(BOOSTER_TYPE_PARAMS) \
00132 { func(BOOSTER_CALL_PARAMS); } \
00133 virtual callable *clone() const \
00134 { return new callable_impl<void,F>(func); } \
00135 }; \
00136 function(){} \
00137 template<typename F> \
00138 function(F func) : call_ptr(new callable_impl<Result,F>(func)) \
00139 {} \
00140 function(function const &other) : call_ptr(other.call_ptr) {} \
00141 template<typename F> \
00142 function const &operator=(F func) \
00143 { \
00144 call_ptr.reset(new callable_impl<Result,F>(func)); \
00145 return *this; \
00146 } \
00147 function const &operator=(function const &other) \
00148 { \
00149 if(this != &other) { call_ptr=other.call_ptr; } \
00150 return *this; \
00151 } \
00152 Result operator()(BOOSTER_TYPE_PARAMS) const \
00153 { \
00154 if(!call_ptr.get()) throw bad_function_call(); \
00155 return call_ptr->call(BOOSTER_CALL_PARAMS); \
00156 } \
00157 bool empty() const { return call_ptr.get()==0; } \
00158 operator bool() const { return !empty(); } \
00159 void swap(function &other) { call_ptr.swap(other.call_ptr); } \
00160 private: \
00161 clone_ptr<callable> call_ptr; \
00162 }; \
00163
00164 #define BOOSTER_TEMPLATE_PARAMS
00165 #define BOOSTER_TEMPLATE_TYPE_PARAMS
00166 #define BOOSTER_TYPE_PARAMS
00167 #define BOOSTER_CALL_PARAMS
00168 BOOSTER_FUNCTION
00169 #undef BOOSTER_TEMPLATE_PARAMS
00170 #undef BOOSTER_TEMPLATE_TYPE_PARAMS
00171 #undef BOOSTER_TYPE_PARAMS
00172 #undef BOOSTER_CALL_PARAMS
00173
00174 #define BOOSTER_TEMPLATE_PARAMS ,typename P1
00175 #define BOOSTER_TEMPLATE_TYPE_PARAMS P1
00176 #define BOOSTER_TYPE_PARAMS P1 a1
00177 #define BOOSTER_CALL_PARAMS a1
00178 BOOSTER_FUNCTION
00179 #undef BOOSTER_TEMPLATE_PARAMS
00180 #undef BOOSTER_TEMPLATE_TYPE_PARAMS
00181 #undef BOOSTER_TYPE_PARAMS
00182 #undef BOOSTER_CALL_PARAMS
00183
00184 #define BOOSTER_TEMPLATE_PARAMS ,typename P1,typename P2
00185 #define BOOSTER_TEMPLATE_TYPE_PARAMS P1, P2
00186 #define BOOSTER_TYPE_PARAMS P1 a1,P2 a2
00187 #define BOOSTER_CALL_PARAMS a1,a2
00188 BOOSTER_FUNCTION
00189 #undef BOOSTER_TEMPLATE_PARAMS
00190 #undef BOOSTER_TEMPLATE_TYPE_PARAMS
00191 #undef BOOSTER_TYPE_PARAMS
00192 #undef BOOSTER_CALL_PARAMS
00193
00194 #define BOOSTER_TEMPLATE_PARAMS ,typename P1,typename P2,typename P3
00195 #define BOOSTER_TEMPLATE_TYPE_PARAMS P1, P2, P3
00196 #define BOOSTER_TYPE_PARAMS P1 a1,P2 a2,P3 a3
00197 #define BOOSTER_CALL_PARAMS a1,a2,a3
00198 BOOSTER_FUNCTION
00199 #undef BOOSTER_TEMPLATE_PARAMS
00200 #undef BOOSTER_TEMPLATE_TYPE_PARAMS
00201 #undef BOOSTER_TYPE_PARAMS
00202 #undef BOOSTER_CALL_PARAMS
00203
00204 #define BOOSTER_TEMPLATE_PARAMS ,typename P1,typename P2,typename P3,typename P4
00205 #define BOOSTER_TEMPLATE_TYPE_PARAMS P1, P2, P3, P4
00206 #define BOOSTER_TYPE_PARAMS P1 a1,P2 a2,P3 a3,P4 a4
00207 #define BOOSTER_CALL_PARAMS a1,a2,a3,a4
00208 BOOSTER_FUNCTION
00209 #undef BOOSTER_TEMPLATE_PARAMS
00210 #undef BOOSTER_TEMPLATE_TYPE_PARAMS
00211 #undef BOOSTER_TYPE_PARAMS
00212 #undef BOOSTER_CALL_PARAMS
00213
00214 #define BOOSTER_TEMPLATE_PARAMS ,typename P1,typename P2,typename P3,typename P4,typename P5
00215 #define BOOSTER_TEMPLATE_TYPE_PARAMS P1, P2, P3, P4, P5
00216 #define BOOSTER_TYPE_PARAMS P1 a1,P2 a2,P3 a3,P4 a4,P5 a5
00217 #define BOOSTER_CALL_PARAMS a1,a2,a3,a4,a5
00218 BOOSTER_FUNCTION
00219 #undef BOOSTER_TEMPLATE_PARAMS
00220 #undef BOOSTER_TEMPLATE_TYPE_PARAMS
00221 #undef BOOSTER_TYPE_PARAMS
00222 #undef BOOSTER_CALL_PARAMS
00223
00224 #define BOOSTER_TEMPLATE_PARAMS ,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6
00225 #define BOOSTER_TEMPLATE_TYPE_PARAMS P1, P2, P3, P4, P5, P6
00226 #define BOOSTER_TYPE_PARAMS P1 a1,P2 a2,P3 a3,P4 a4,P5 a5,P6 a6
00227 #define BOOSTER_CALL_PARAMS a1,a2,a3,a4,a5,a6
00228 BOOSTER_FUNCTION
00229 #undef BOOSTER_TEMPLATE_PARAMS
00230 #undef BOOSTER_TEMPLATE_TYPE_PARAMS
00231 #undef BOOSTER_TYPE_PARAMS
00232 #undef BOOSTER_CALL_PARAMS
00233
00234 #define BOOSTER_TEMPLATE_PARAMS ,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7
00235 #define BOOSTER_TEMPLATE_TYPE_PARAMS P1, P2, P3, P4, P5, P6, P7
00236 #define BOOSTER_TYPE_PARAMS P1 a1,P2 a2,P3 a3,P4 a4,P5 a5,P6 a6,P7 a7
00237 #define BOOSTER_CALL_PARAMS a1,a2,a3,a4,a5,a6,a7
00238 BOOSTER_FUNCTION
00239 #undef BOOSTER_TEMPLATE_PARAMS
00240 #undef BOOSTER_TEMPLATE_TYPE_PARAMS
00241 #undef BOOSTER_TYPE_PARAMS
00242 #undef BOOSTER_CALL_PARAMS
00243
00244 #define BOOSTER_TEMPLATE_PARAMS ,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7,typename P8
00245 #define BOOSTER_TEMPLATE_TYPE_PARAMS P1, P2, P3, P4, P5, P6, P7, P8
00246 #define BOOSTER_TYPE_PARAMS P1 a1,P2 a2,P3 a3,P4 a4,P5 a5,P6 a6,P7 a7,P8 a8
00247 #define BOOSTER_CALL_PARAMS a1,a2,a3,a4,a5,a6,a7,a8
00248 BOOSTER_FUNCTION
00249 #undef BOOSTER_TEMPLATE_PARAMS
00250 #undef BOOSTER_TEMPLATE_TYPE_PARAMS
00251 #undef BOOSTER_TYPE_PARAMS
00252 #undef BOOSTER_CALL_PARAMS
00253
00254 #undef BOOSTER_FUNCTION
00255
00256 #endif // DOC
00257
00258 }
00259
00260
00261 #endif