casa
$Rev:20696$
|
00001 //# functor.h: declaration & definition of functors + args 00002 //# 00003 //# Copyright (C) 2011 00004 //# Associated Universities, Inc. Washington DC, USA. 00005 //# 00006 //# This library is free software; you can redistribute it and/or modify it 00007 //# under the terms of the GNU Library General Public License as published by 00008 //# the Free Software Foundation; either version 2 of the License, or (at your 00009 //# option) any later version. 00010 //# 00011 //# This library is distributed in the hope that it will be useful, but WITHOUT 00012 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00013 //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00014 //# License for more details. 00015 //# 00016 //# You should have received a copy of the GNU Library General Public License 00017 //# along with this library; if not, write to the Free Software Foundation, 00018 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. 00019 //# 00020 //# Correspondence concerning AIPS++ should be addressed as follows: 00021 //# Internet email: aips2-request@nrao.edu. 00022 //# Postal address: AIPS++ Project Office 00023 //# National Radio Astronomy Observatory 00024 //# 520 Edgemont Road 00025 //# Charlottesville, VA 22903-2475 USA 00026 //# 00027 //# $Id$ 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