casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
functor.h
Go to the documentation of this file.
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