Image Component Library (ICL)
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Function.h
Go to the documentation of this file.
00001 /********************************************************************
00002 **                Image Component Library (ICL)                    **
00003 **                                                                 **
00004 ** Copyright (C) 2006-2013 CITEC, University of Bielefeld          **
00005 **                         Neuroinformatics Group                  **
00006 ** Website: www.iclcv.org and                                      **
00007 **          http://opensource.cit-ec.de/projects/icl               **
00008 **                                                                 **
00009 ** File   : ICLUtils/src/ICLUtils/Function.h                       **
00010 ** Module : ICLUtils                                               **
00011 ** Authors: Christof Elbrechter                                    **
00012 **                                                                 **
00013 **                                                                 **
00014 ** GNU LESSER GENERAL PUBLIC LICENSE                               **
00015 ** This file may be used under the terms of the GNU Lesser General **
00016 ** Public License version 3.0 as published by the                  **
00017 **                                                                 **
00018 ** Free Software Foundation and appearing in the file LICENSE.LGPL **
00019 ** included in the packaging of this file.  Please review the      **
00020 ** following information to ensure the license requirements will   **
00021 ** be met: http://www.gnu.org/licenses/lgpl-3.0.txt                **
00022 **                                                                 **
00023 ** The development of this software was supported by the           **
00024 ** Excellence Cluster EXC 277 Cognitive Interaction Technology.    **
00025 ** The Excellence Cluster EXC 277 is a grant of the Deutsche       **
00026 ** Forschungsgemeinschaft (DFG) in the context of the German       **
00027 ** Excellence Initiative.                                          **
00028 **                                                                 **
00029 ********************************************************************/
00030 
00031 #pragma once
00032 
00033 #include <ICLUtils/SmartPtr.h>
00034 #include <functional>
00035 #include <ICLUtils/CompatMacros.h>
00036 
00037 namespace icl{
00038   namespace utils{
00039     struct NO_ARG;
00041     // FunctionImpl classes and specializations /////////////
00043   
00045 
00046     template<class R=void, class A=NO_ARG, class B=NO_ARG, class C=NO_ARG>
00047     struct FunctionImpl{
00049       virtual R operator()(A a, B b, C c) const = 0;
00050       virtual ~FunctionImpl(){}
00051     };
00052     
00054 
00055     template<class R, class A, class B>
00056     struct FunctionImpl<R, A, B, NO_ARG>{
00058       virtual R operator()(A a, B b) const = 0;
00059       virtual ~FunctionImpl(){}
00060     };
00061     
00063 
00064     template<class R, class A>
00065     struct FunctionImpl<R, A, NO_ARG>{
00067       virtual R operator()(A a) const = 0;
00068       virtual ~FunctionImpl(){}
00069         };
00070 
00072 
00073         template<class R>
00074         struct FunctionImpl<R, NO_ARG>{
00076           virtual R operator()() const = 0;
00077           virtual ~FunctionImpl(){}
00078         };
00079   
00081     // Member Function Implementations ///////////////////////
00083     
00085 
00089     template <class Object, class R=void, class A=NO_ARG, class B=NO_ARG, class C=NO_ARG>
00090     struct MemberFunctionImpl : public FunctionImpl<R, A, B, C>{
00091       Object *obj;
00092       R (Object::*method)(A, B, C);
00093       virtual R operator()(A a,B b,C c) const { return (obj->*method)(a, b, c); }
00094     };
00095     
00097     template <class Object, class R, class A, class B>
00098     struct MemberFunctionImpl<Object, R, A, B, NO_ARG> : public FunctionImpl<R, A, B>{
00099       Object *obj;
00100       R (Object::*method)(A, B);
00101       virtual R operator()(A a,B b) const { return (obj->*method)(a, b); }
00102     };
00103   
00104     template <class Object, class R, class A>
00105     struct MemberFunctionImpl<Object, R, A, NO_ARG, NO_ARG> : public FunctionImpl<R, A>{
00106       Object *obj;
00107       R (Object::*method)(A);
00108       virtual R operator()(A a) const { return (obj->*method)(a); }
00109     };
00110     
00111     template <class Object, class R>
00112     struct MemberFunctionImpl<Object, R, NO_ARG, NO_ARG, NO_ARG> : public FunctionImpl<R>{
00113       Object *obj;
00114       R (Object::*method)();
00115       virtual R operator()() const { return (obj->*method)(); }
00116     };
00119 
00120     // CONST Member Function Implementations /////////////////
00122   
00124 
00128     template <class Object, class R=void, class A=NO_ARG, class B=NO_ARG, class C=NO_ARG>
00129     struct ConstMemberFunctionImpl : public FunctionImpl<R, A, B, C>{
00130       const Object *obj;
00131       R (Object::*method)(A, B, C) const;
00132       virtual R operator()(A a,B b,C c) const { return (obj->*method)(a, b, c); }
00133     };
00136     template <class Object, class R, class A, class B>
00137     struct ConstMemberFunctionImpl<Object, R, A, B, NO_ARG> : public FunctionImpl<R, A, B>{
00138       const Object *obj;
00139       R (Object::*method)(A, B) const;
00140       virtual R operator()(A a,B b) const { return (obj->*method)(a, b); }
00141     };
00142   
00143     template <class Object, class R, class A>
00144     struct ConstMemberFunctionImpl<Object, R, A, NO_ARG> : public FunctionImpl<R, A>{
00145       const Object *obj;
00146       R (Object::*method)(A) const;
00147       virtual R operator()(A a) const { return (obj->*method)(a); }
00148     };
00149     
00150     template <class Object, class R>
00151     struct ConstMemberFunctionImpl<Object, R, NO_ARG> : public FunctionImpl<R>{
00152       const Object *obj;
00153       R (Object::*method)() const;
00154       virtual R operator()() const { return (obj->*method)(); }
00155     };
00158 
00159     // Functor Member Functions //////////////////////////////
00161   
00163 
00167     template <class Object, class R=void, class A=NO_ARG, class B=NO_ARG, class C=NO_ARG>
00168     struct FunctorFunctionImpl : public FunctionImpl<R, A, B, C>{
00169       Object *obj;
00170       virtual R operator()(A a,B b, C c) const { return (*obj)(a,b,c); }
00171     };
00172     
00174     template <class Object, class R, class A, class B>
00175     struct FunctorFunctionImpl<Object, R, A, B, NO_ARG> : public FunctionImpl<R, A, B>{
00176       Object *obj;
00177       virtual R operator()(A a,B b) const { return (*obj)(a,b); }
00178     };
00179   
00180     template <class Object, class R, class A>
00181     struct FunctorFunctionImpl<Object, R, A, NO_ARG> : public FunctionImpl<R, A>{
00182       Object *obj;
00183       virtual R operator()(A a) const { return (*obj)(a); }
00184     };
00185     template <class Object, class R>
00186     struct FunctorFunctionImpl<Object, R, NO_ARG> : public FunctionImpl<R>{
00187       Object *obj;
00188       virtual R operator()() const { return (*obj)(); }
00189     };
00192 
00193     // CONST Functor Member Functions ////////////////////////
00195     
00197 
00201     template <class Object, class R=void, class A=NO_ARG, class B=NO_ARG, class C=NO_ARG>
00202     struct ConstFunctorFunctionImpl : public FunctionImpl<R, A, B, C>{
00203       const Object *obj;
00204       virtual R operator()(A a,B b, C c) const { return (*obj)(a,b,c); }
00205     };
00206     
00208     template <class Object, class R, class A, class B>
00209     struct ConstFunctorFunctionImpl<Object, R, A, B, NO_ARG> : public FunctionImpl<R, A, B>{
00210       const Object *obj;
00211       virtual R operator()(A a,B b) const { return (*obj)(a,b); }
00212     };
00213   
00214     template <class Object, class R, class A>
00215     struct ConstFunctorFunctionImpl<Object, R, A, NO_ARG> : public FunctionImpl<R, A>{
00216       const Object *obj;
00217       virtual R operator()(A a) const { return (*obj)(a); }
00218     };
00219     template <class Object, class R>
00220     struct ConstFunctorFunctionImpl<Object, R, NO_ARG> : public FunctionImpl<R>{
00221       const Object *obj;
00222       virtual R operator()() const { return (*obj)(); }
00223     };
00226 
00227     // Global Function Wrappers //////////////////////////////
00229     
00230    
00232 
00236     template <class R=void, class A=NO_ARG, class B=NO_ARG, class C=NO_ARG>
00237     struct GlobalFunctionImpl : public FunctionImpl<R, A, B, C>{
00238       R (*global_function)(A, B, C);
00239       virtual R operator()(A a,B b,C c) const { return global_function(a, b,c); }
00240     };
00242     template <class R, class A, class B>
00243     struct GlobalFunctionImpl<R, A, B, NO_ARG> : public FunctionImpl<R, A, B>{
00244       R (*global_function)(A, B);
00245       virtual R operator()(A a,B b) const { return global_function(a, b); }
00246     };
00247   
00248     template <class R, class A>
00249     struct GlobalFunctionImpl<R, A, NO_ARG> : public FunctionImpl<R, A>{
00250       R (*global_function)(A);
00251       virtual R operator()(A a) const { return global_function(a); }
00252     };
00253     template <class R>
00254     struct GlobalFunctionImpl<R, NO_ARG> : public FunctionImpl<R>{
00255       R (*global_function)();
00256       virtual R operator()() const { return global_function(); }
00257     };
00260 
00261     // The Function class ////////////////////////////////////
00263     
00265 
00283     template<class R=void, class A=NO_ARG, class B=NO_ARG, class C=NO_ARG> 
00284     struct Function {
00286       Function(){}
00287       
00289       Function(FunctionImpl<R,A,B,C> *impl):impl(impl){}
00290   
00292       Function(icl::utils::SmartPtr<FunctionImpl<R,A,B,C> >impl):impl(impl){}
00293   
00295 
00298       Function(R (*global_function)(A,B,C)):impl(new GlobalFunctionImpl<R,A,B,C>){
00299         ((GlobalFunctionImpl<R,A,B,C>*)(impl.get()))->global_function = global_function;
00300       }
00301       
00303       icl::utils::SmartPtr<FunctionImpl<R,A,B,C> >impl;
00304       
00306 
00308       R operator()(A a, B b, C c) const { return (*impl)(a,b,c); }
00309       
00311       operator bool() const { return impl; }
00312   
00313       operator Function<R,A,B,C> () const { return (*(const Function<R,A,B,C>*)(this)); }
00314     };
00315     
00317     template<class R, class A, class B> 
00318     struct Function<R, A, B, NO_ARG> : public std::binary_function<A, B, R>{
00319       Function(){}
00320       Function(FunctionImpl<R,A,B> *impl):impl(impl){}
00321       Function(icl::utils::SmartPtr<FunctionImpl<R,A,B> >impl):impl(impl){}
00322       Function(R (*global_function)(A,B)):impl(new GlobalFunctionImpl<R,A,B>){
00323         ((GlobalFunctionImpl<R,A,B>*)(impl.get()))->global_function = global_function;
00324       }
00325       icl::utils::SmartPtr<FunctionImpl<R,A,B> >impl;
00326       R operator()(A a, B b) const { return (*impl)(a,b); }
00327       operator bool() const { return impl; }
00328       
00329       operator Function<R,A,B> () const { return (*(const Function<R,A,B>*)(this)); }
00330     };
00331   
00332     template<class R, class A> 
00333     struct Function<R, A, NO_ARG> : public std::unary_function<A, R>{
00334       Function(){}
00335       Function(FunctionImpl<R,A> *impl):impl(impl){}
00336       Function(icl::utils::SmartPtr<FunctionImpl<R,A> >impl):impl(impl){}
00337       Function(R (*global_function)(A)):impl(new GlobalFunctionImpl<R,A>){
00338         ((GlobalFunctionImpl<R,A>*)(impl.get()))->global_function = global_function;
00339       }
00340       icl::utils::SmartPtr<FunctionImpl<R,A> >impl;
00341           R operator()(A a) const { return (*impl)(a); }
00342       operator bool() const { return impl; }
00343       
00344       operator Function<R,A> () const { return (*(const Function<R,A>*)(this)); }
00345     };
00346     template<class R> 
00347     struct Function<R, NO_ARG>{
00348       typedef R result_type;
00349       Function(){}
00350       Function(FunctionImpl<R> *impl):impl(impl){}
00351       Function(icl::utils::SmartPtr<FunctionImpl<R> >impl):impl(impl){}
00352       Function(R (*global_function)()):impl(new GlobalFunctionImpl<R>){
00353         ((GlobalFunctionImpl<R>*)(impl.get()))->global_function = global_function;
00354       }
00355           icl::utils::SmartPtr<FunctionImpl<R> >impl;
00356           R operator()() const { return (*impl)(); }
00357   
00358       operator bool() const { return impl; }
00359   
00360       operator Function<R> () const { return (*(const Function<R>*)(this)); }
00361     };
00367 
00368     // Function creator functions (from member functions /////
00370   
00372 
00375     template<class Object, class R, class A, class B, class C>
00376     Function<R, A, B, C> function(Object &obj, R(Object::*method)(A, B, C)){
00377       MemberFunctionImpl<Object,R,A,B,C> *impl = new MemberFunctionImpl<Object,R,A,B,C>;
00378       impl->obj = &obj;
00379       impl->method = method;
00380       return Function<R,A,B,C>(impl);
00381     } 
00382     
00384 
00387     template<class Object,class R, class A, class B>
00388     Function<R, A, B> function(Object &obj, R(Object::*method)(A, B)){
00389       MemberFunctionImpl<Object,R,A,B> *impl = new MemberFunctionImpl<Object,R,A,B>;
00390       impl->obj = &obj;
00391       impl->method = method;
00392       return Function<R,A,B>(impl);
00393     } 
00394     
00396 
00399     template<class Object,class R, class A>
00400     Function<R, A> function(Object &obj, R(Object::*method)(A)){
00401       MemberFunctionImpl<Object,R,A> *impl = new MemberFunctionImpl<Object,R,A>;
00402       impl->obj = &obj;
00403       impl->method = method;
00404       return Function<R,A>(impl);
00405     } 
00406   
00408 
00412     template<class Object,class R>
00413     Function<R> function(Object &obj, R(Object::*method)()){
00414       MemberFunctionImpl<Object,R> *impl = new MemberFunctionImpl<Object,R>;
00415       impl->obj = &obj;
00416       impl->method = method;
00417       return Function<R>(impl);
00418     } 
00419   
00421 
00424     template<class Object,class R,class A,class B,class C>
00425     Function<R, A, B, C> function(const Object &obj, R(Object::*method)(A a, B b, C c) const){
00426       ConstMemberFunctionImpl<Object,R,A,B,C> *impl = new ConstMemberFunctionImpl<Object,R,A,B,C>;
00427       impl->obj = &obj;
00428       impl->method = method;
00429       return Function<R,A,B,C>(impl);
00430     } 
00431     
00433 
00436     template<class Object,class R,class A,class B>
00437     Function<R, A, B> function(const Object &obj, R(Object::*method)(A a, B b) const){
00438       ConstMemberFunctionImpl<Object,R,A,B> *impl = new ConstMemberFunctionImpl<Object,R,A,B>;
00439       impl->obj = &obj;
00440       impl->method = method;
00441       return Function<R,A,B>(impl);
00442     } 
00444 
00447     template<class Object,class R,class A>
00448     Function<R, A> function(const Object &obj, R(Object::*method)(A a) const){
00449       ConstMemberFunctionImpl<Object,R,A> *impl = new ConstMemberFunctionImpl<Object,R,A>;
00450       impl->obj = &obj;
00451       impl->method = method;
00452       return Function<R,A>(impl);
00453     } 
00455 
00459     template<class Object,class R>
00460     Function<R> function(const Object &obj, R(Object::*method)() const){
00461       ConstMemberFunctionImpl<Object,R> *impl = new ConstMemberFunctionImpl<Object,R>;
00462       impl->obj = &obj;
00463       impl->method = method;
00464       return Function<R>(impl);
00465     } 
00466   
00468 
00471     template<class Object,class R, class A, class B, class C>
00472     Function<R, A, B, C> function(Object *obj, R(Object::*method)(A, B, C)){ return function<Object, R, A, B, C>(*obj, method); }
00473   
00475 
00478     template<class Object,class R, class A, class B>
00479     Function<R, A, B> function(Object *obj, R(Object::*method)(A, B)){ return function<Object, R, A, B>(*obj, method); }
00480     
00482 
00485     template<class Object,class R, class A>
00486     Function<R, A> function(Object *obj, R(Object::*method)(A)){ return function<Object, R, A>(*obj, method); }
00487     
00489 
00493     template<class Object,class R>
00494     Function<R> function(Object *obj, R(Object::*method)()){ return function<Object, R>(*obj, method); }
00495   
00497 
00500     template<class Object,class R, class A, class B, class C>
00501     Function<R, A, B, C> function(const Object *obj, R(Object::*method)(A, B, C) const){ return function<Object, R, A, B, C>(*obj, method); }
00502    
00504 
00507     template<class Object,class R, class A, class B>
00508     Function<R, A, B> function(const Object *obj, R(Object::*method)(A, B) const){ return function<Object, R, A, B>(*obj, method); }
00509   
00511 
00514     template<class Object,class R, class A>
00515     Function<R, A> function(const Object *obj, R(Object::*method)(A) const){ return function<Object, R, A>(*obj, method); }
00516     
00518 
00522     template<class Object,class R>
00523     Function<R> function(const Object *obj, R(Object::*method)() const){ return function<Object, R>(*obj, method); }
00524   
00525     
00527     // Function creator functions (from functors) ////////////
00529     
00531 
00532     template <class R = void, class A = NO_ARG, class B = NO_ARG, class C = NO_ARG> struct SelectFunctor{};
00533     
00535 
00539     template<class Object,class R, class A, class B, class C>
00540     Function<R, A, B, C> function(Object &obj, SelectFunctor<R, A, B, C>){
00541       FunctorFunctionImpl<Object,R,A,B,C>  *impl = new FunctorFunctionImpl<Object,R,A,B,C>;
00542       impl->obj = &obj;
00543       return Function<R,A,B,C>(impl);
00544     } 
00545   
00547 
00551     template<class Object,class R, class A, class B, class C>
00552     Function<R, A, B> function(const Object &obj, SelectFunctor<R, A, B, C>){
00553       ConstFunctorFunctionImpl<Object,R,A,B,C>  *impl = new ConstFunctorFunctionImpl<Object,R,A,B,C>;
00554       impl->obj = &obj;
00555       return Function<R,A,B,C>(impl);
00556     } 
00557   
00559 
00560     template<class Object>
00561     Function<> function(Object &obj){
00562       return function(obj,SelectFunctor<void,NO_ARG,NO_ARG,NO_ARG>());
00563     } 
00564   
00566 
00567     template<class Object>
00568     Function<> function(const Object &obj){
00569       return function(obj,SelectFunctor<void,NO_ARG,NO_ARG,NO_ARG>());
00570     } 
00571   
00573 
00577     template<class Object,class R, class A, class B, class C>
00578     Function<R, A, B, C> function(Object *obj, SelectFunctor<R, A, B, C> selector){ return function<Object, R, A, B, C>(*obj, selector); }
00579     
00581 
00585     template<class Object,class R, class A, class B, class C>
00586     Function<R, A, B, C> function(const Object *obj, SelectFunctor<R, A, B, C> selector){ return function<Object, R, A, B, C>(*obj, selector); }
00587     
00588     
00590     // Function creator functions (from global functions) ////
00592   
00594 
00597     template<class R, class A, class B, class C>
00598     Function<R, A, B, C> function(R(*global_function)(A a, B b, C c)){
00599       return Function<R,A,B,C>(global_function);
00600     } 
00601     
00603 
00606     template<class R, class A, class B>
00607     Function<R, A, B> function(R(*global_function)(A a, B b)){
00608       return Function<R,A,B>(global_function);
00609     } 
00610   
00611     
00613 
00616     template<class R, class A>
00617     Function<R, A> function(R(*global_function)(A a)){
00618       return Function<R,A>(global_function);
00619     } 
00620   
00622 
00625     template<class R>
00626     Function<R> function(R(*global_function)()){
00627       return Function<R>(global_function);
00628     }
00629   } // namespace utils
00630 }
00631 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines