00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifndef __casadbus_functor_h__
00030 #define __casadbus_functor_h__
00031 #include <casadbus/types/ptr.h>
00032 #include <string>
00033 #include <stdexcept>
00034
00035 namespace casa {
00036 namespace functor {
00037
00038 class args {
00039 public:
00040 virtual ~args( ) { }
00041 };
00042
00043 template<class T1> class args01 : public args {
00044 public:
00045 args01( T1 v1 ) : a1(v1) { }
00046 T1 one( ) { return a1; }
00047 private:
00048 T1 a1;
00049 };
00050
00051 template<class T1, class T2> class args02 : public args {
00052 public:
00053 args02( T1 v1, T2 v2 ) : a1(v1), a2(v2) { }
00054 T1 one( ) { return a1; }
00055 T2 two( ) { return a2; }
00056 private:
00057 T1 a1;
00058 T2 a2;
00059 };
00060
00061 template<class T1, class T2, class T3> class args03 : public args {
00062 public:
00063 args03( T1 v1, T2 v2, T3 v3 ) : a1(v1), a2(v2), a3(v3) { }
00064 T1 one( ) { return a1; }
00065 T2 two( ) { return a2; }
00066 T3 three( ) { return a3; }
00067 private:
00068 T1 a1;
00069 T2 a2;
00070 T3 a3;
00071 };
00072
00073 template<class T1, class T2, class T3, class T4> class args04 : public args {
00074 public:
00075 args04( T1 v1, T2 v2, T3 v3, T4 v4 ) : a1(v1), a2(v2), a3(v3), a4(v4) { }
00076 T1 one( ) { return a1; }
00077 T2 two( ) { return a2; }
00078 T3 three( ) { return a3; }
00079 T4 four( ) { return a4; }
00080 private:
00081 T1 a1;
00082 T2 a2;
00083 T3 a3;
00084 T4 a4;
00085 };
00086
00087
00088 class invocation_exception : public std::runtime_error {
00089 public:
00090 invocation_exception( ) : std::runtime_error( "functor/argument mismatch" ) { }
00091 };
00092
00093 class f_ {
00094 public:
00095 f_( ) { }
00096 virtual void invoke( args *a ) = 0;
00097 virtual ~f_( ) { }
00098 };
00099
00100 class f {
00101 public:
00102 f( const f &other ) : ptr(other.ptr) { }
00103 void operator()( args *a ) { ptr->invoke( a ); }
00104 void operator()( args &a ) { ptr->invoke( &a ); }
00105 std::string state( ) const { return ptr.state( ); }
00106 virtual ~f( ) { }
00107 private:
00108 f( );
00109 f( f_ *p ) : ptr(p) { }
00110 void operator=(const f &);
00111 memory::cptr<f_> ptr;
00112
00113 template <class C> friend f make( C *o, void (C::*i)( ) );
00114 template <class C, class P1> friend f make( C *o, void (C::*i)(P1) );
00115 template <class C, class P1, class P2> friend f make( C *o, void (C::*i)(P1,P2) );
00116 template <class C, class P1, class P2, class P3> friend f make( C *o, void (C::*i)(P1,P2,P3) );
00117 template <class C, class P1, class P2, class P3, class P4> friend f make( C *o, void (C::*i)(P1,P2,P3,P4) );
00118 };
00119
00120
00121 template <class C> class f00 : public f_ {
00122 public:
00123 f00( C *o, void (C::*i)( ) ) : obj(o), impl(i) { }
00124 void invoke( ) { (*obj.*impl)( ); }
00125 void invoke( args *ga ) { (*this)( ); }
00126 private:
00127 C *obj;
00128 void (C::*impl)( );
00129 };
00130
00131 template <class C, class P1> class f01 : public f_ {
00132 public:
00133 f01( C *o, void (C::*i)(P1) ) : obj(o), impl(i) { }
00134 void invoke( P1 a1 ) { (*obj.*impl)(a1); }
00135 void invoke( args *ga ) {
00136 args01<P1> *a = dynamic_cast<args01<P1>*>(ga);
00137 if ( a ) { (*this)(a->one()); }
00138 else { throw invocation_exception( ); }
00139 }
00140 private:
00141 C *obj;
00142 void (C::*impl)(P1);
00143 };
00144
00145 template <class C, class P1, class P2> class f02 : public f_ {
00146 public:
00147 f02( C *o, void (C::*i)(P1,P2) ) : obj(o), impl(i) { }
00148 void invoke( P1 a1, P2 a2 ) { (*obj.*impl)(a1,a2); }
00149 void invoke( args *ga ) {
00150 args02<P1,P2> *a = dynamic_cast<args02<P1,P2>*>(ga);
00151 if ( a ) { invoke(a->one(),a->two()); }
00152 else { throw invocation_exception( ); }
00153 }
00154 private:
00155 C *obj;
00156 void (C::*impl)(P1,P2);
00157 };
00158
00159 template <class C, class P1, class P2, class P3> class f03 : public f_ {
00160 public:
00161 f03( C *o, void (C::*i)(P1,P2,P3) ) : obj(o), impl(i) { }
00162 void invoke( P1 a1, P2 a2, P3 a3 ) { (*obj.*impl)(a1,a2,a3); }
00163 void invoke( args *ga ) {
00164 args03<P1,P2,P3> *a = dynamic_cast<args03<P1,P2,P3>*>(ga);
00165 if ( a ) { (*this)(a->one(),a->two(),a->three()); }
00166 else { throw invocation_exception( ); }
00167 }
00168 private:
00169 C *obj;
00170 void (C::*impl)(P1,P2,P3);
00171 };
00172
00173 template <class C, class P1, class P2, class P3, class P4> class f04 : public f_ {
00174 public:
00175 f04( C *o, void (C::*i)(P1,P2,P3,P4) ) : obj(o), impl(i) { }
00176 void invoke( P1 a1, P2 a2, P3 a3, P4 a4 ) { (*obj.*impl)(a1,a2,a3,a4); }
00177 void invoke( args *ga ) {
00178 args04<P1,P2,P3,P4> *a = dynamic_cast<args04<P1,P2,P3,P4>*>(ga);
00179 if ( a ) { (*this)(a->one(),a->two(),a->three(),a->four()); }
00180 else { throw invocation_exception( ); }
00181 }
00182 private:
00183 C *obj;
00184 void (C::*impl)(P1,P2,P3,P4);
00185 };
00186
00187 template <class C> f make( C *o, void (C::*i)( ) )
00188 { return f(new functor::f00<C>( o, i )); }
00189 template <class C, class P1> f make( C *o, void (C::*i)(P1) )
00190 { return f(new functor::f01<C,P1>( o, i )); }
00191 template <class C, class P1, class P2> f make( C *o, void (C::*i)(P1,P2) )
00192 { return f(new functor::f02<C,P1,P2>( o, i )); }
00193 template <class C, class P1, class P2, class P3> f make( C *o, void (C::*i)(P1,P2,P3) )
00194 { return f(new functor::f03<C,P1,P2,P3>( o, i )); }
00195 template <class C, class P1, class P2, class P3, class P4> f make( C *o, void (C::*i)(P1,P2,P3,P4) )
00196 { return f(new functor::f04<C,P1,P2,P3,P4>( o, i )); }
00197
00198 }
00199 }
00200
00201 #endif