CppCMS
booster/function.h
00001 //
00002 //  Copyright (C) 2009-2012 Artyom Beilis (Tonkikh)
00003 //
00004 //  Distributed under the Boost Software License, Version 1.0. (See
00005 //  accompanying file LICENSE_1_0.txt or copy at
00006 //  http://www.boost.org/LICENSE_1_0.txt)
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 } // booster
00259 
00260 
00261 #endif