/********************************************************************
**                Image Component Library (ICL)                    **
**                                                                 **
** Copyright (C) 2006-2013 CITEC, University of Bielefeld          **
**                         Neuroinformatics Group                  **
** Website: www.iclcv.org and                                      **
**          http://opensource.cit-ec.de/projects/icl               **
**                                                                 **
** File   : ICLUtils/src/ICLUtils/Function.h                       **
** Module : ICLUtils                                               **
** Authors: Christof Elbrechter                                    **
**                                                                 **
**                                                                 **
** GNU LESSER GENERAL PUBLIC LICENSE                               **
** This file may be used under the terms of the GNU Lesser General **
** Public License version 3.0 as published by the                  **
**                                                                 **
** Free Software Foundation and appearing in the file LICENSE.LGPL **
** included in the packaging of this file.  Please review the      **
** following information to ensure the license requirements will   **
** be met: http://www.gnu.org/licenses/lgpl-3.0.txt                **
**                                                                 **
** The development of this software was supported by the           **
** Excellence Cluster EXC 277 Cognitive Interaction Technology.    **
** The Excellence Cluster EXC 277 is a grant of the Deutsche       **
** Forschungsgemeinschaft (DFG) in the context of the German       **
** Excellence Initiative.                                          **
**                                                                 **
********************************************************************/

#pragma once

#include <ICLUtils/SmartPtr.h>
#include <functional>
#include <ICLUtils/CompatMacros.h>

namespace icl{
  namespace utils{
    struct NO_ARG;
    /////////////////////////////////////////////////////////
    // FunctionImpl classes and specializations /////////////
    /////////////////////////////////////////////////////////
  
    /// General Implementation for binary functions \ingroup FUNCTION
    /** @see \ref FUNCTION_SECTION */
    template<class R=void, class A=NO_ARG, class B=NO_ARG, class C=NO_ARG>
    struct FunctionImpl{
      /// function interface
      virtual R operator()(A a, B b, C c) const = 0;
      virtual ~FunctionImpl(){}
    };
    
    /// Special Implementation for unary functions \ingroup FUNCTION
    /** @see \ref FUNCTION_SECTION */
    template<class R, class A, class B>
    struct FunctionImpl<R, A, B, NO_ARG>{
      /// function interface
      virtual R operator()(A a, B b) const = 0;
      virtual ~FunctionImpl(){}
    };
    
    /// Special Implementation for unary functions \ingroup FUNCTION
    /** @see \ref FUNCTION_SECTION */
    template<class R, class A>
    struct FunctionImpl<R, A, NO_ARG>{
      /// function interface
      virtual R operator()(A a) const = 0;
      virtual ~FunctionImpl(){}
	};

	/// Special Implementation for void functions \ingroup FUNCTION
	/** @see \ref FUNCTION_SECTION */
	template<class R>
	struct FunctionImpl<R, NO_ARG>{
	  /// function interface
	  virtual R operator()() const = 0;
	  virtual ~FunctionImpl(){}
	};
  
    //////////////////////////////////////////////////////////
    // Member Function Implementations ///////////////////////
    //////////////////////////////////////////////////////////
    
    /// FunctionImpl implementation for member functions \ingroup FUNCTION
    /** This class should not be used directly! Use the overloaded
        icl::utils::function - template instead. The class template is 
        specialized for member functions with less parameters.
        @see \ref FUNCTION_SECTION */
    template <class Object, class R=void, class A=NO_ARG, class B=NO_ARG, class C=NO_ARG>
    struct MemberFunctionImpl : public FunctionImpl<R, A, B, C>{
      Object *obj;
      R (Object::*method)(A, B, C);
      virtual R operator()(A a,B b,C c) const { return (obj->*method)(a, b, c); }
    };
    
    /** \cond **/
    template <class Object, class R, class A, class B>
    struct MemberFunctionImpl<Object, R, A, B, NO_ARG> : public FunctionImpl<R, A, B>{
      Object *obj;
      R (Object::*method)(A, B);
      virtual R operator()(A a,B b) const { return (obj->*method)(a, b); }
    };
  
    template <class Object, class R, class A>
    struct MemberFunctionImpl<Object, R, A, NO_ARG, NO_ARG> : public FunctionImpl<R, A>{
      Object *obj;
      R (Object::*method)(A);
      virtual R operator()(A a) const { return (obj->*method)(a); }
    };
    
    template <class Object, class R>
    struct MemberFunctionImpl<Object, R, NO_ARG, NO_ARG, NO_ARG> : public FunctionImpl<R>{
      Object *obj;
      R (Object::*method)();
      virtual R operator()() const { return (obj->*method)(); }
    };
    /** \endcond **/
  
    //////////////////////////////////////////////////////////
    // CONST Member Function Implementations /////////////////
    //////////////////////////////////////////////////////////
  
    /// FunctionImpl implementation for const member functions \ingroup FUNCTION
    /** This class should not be used directly! Use the overloaded
        icl::utils::function - template instead. The class template is 
        specialized for member functions with less parameters.
        @see \ref FUNCTION_SECTION */
    template <class Object, class R=void, class A=NO_ARG, class B=NO_ARG, class C=NO_ARG>
    struct ConstMemberFunctionImpl : public FunctionImpl<R, A, B, C>{
      const Object *obj;
      R (Object::*method)(A, B, C) const;
      virtual R operator()(A a,B b,C c) const { return (obj->*method)(a, b, c); }
    };
    /** \cond **/
  
    template <class Object, class R, class A, class B>
    struct ConstMemberFunctionImpl<Object, R, A, B, NO_ARG> : public FunctionImpl<R, A, B>{
      const Object *obj;
      R (Object::*method)(A, B) const;
      virtual R operator()(A a,B b) const { return (obj->*method)(a, b); }
    };
  
    template <class Object, class R, class A>
    struct ConstMemberFunctionImpl<Object, R, A, NO_ARG> : public FunctionImpl<R, A>{
      const Object *obj;
      R (Object::*method)(A) const;
      virtual R operator()(A a) const { return (obj->*method)(a); }
    };
    
    template <class Object, class R>
    struct ConstMemberFunctionImpl<Object, R, NO_ARG> : public FunctionImpl<R>{
      const Object *obj;
      R (Object::*method)() const;
      virtual R operator()() const { return (obj->*method)(); }
    };
    /** \endcond **/
    
    //////////////////////////////////////////////////////////
    // Functor Member Functions //////////////////////////////
    //////////////////////////////////////////////////////////
  
    /// FunctionImpl implementation for Functors \ingroup FUNCTION
    /** This class should not be used directly! Use the overloaded
        icl::utils::function - template instead. The class template is 
        specialized for member functions with less parameters.
        @see \ref FUNCTION_SECTION */
    template <class Object, class R=void, class A=NO_ARG, class B=NO_ARG, class C=NO_ARG>
    struct FunctorFunctionImpl : public FunctionImpl<R, A, B, C>{
      Object *obj;
      virtual R operator()(A a,B b, C c) const { return (*obj)(a,b,c); }
    };
    
    /** \cond **/
    template <class Object, class R, class A, class B>
    struct FunctorFunctionImpl<Object, R, A, B, NO_ARG> : public FunctionImpl<R, A, B>{
      Object *obj;
      virtual R operator()(A a,B b) const { return (*obj)(a,b); }
    };
  
    template <class Object, class R, class A>
    struct FunctorFunctionImpl<Object, R, A, NO_ARG> : public FunctionImpl<R, A>{
      Object *obj;
      virtual R operator()(A a) const { return (*obj)(a); }
    };
    template <class Object, class R>
    struct FunctorFunctionImpl<Object, R, NO_ARG> : public FunctionImpl<R>{
      Object *obj;
      virtual R operator()() const { return (*obj)(); }
    };
    /** ¸\endcond **/
  
    //////////////////////////////////////////////////////////
    // CONST Functor Member Functions ////////////////////////
    //////////////////////////////////////////////////////////
    
    /// FunctionImpl implementation for functors of const objects \ingroup FUNCTION
    /** This class should not be used directly! Use the overloaded
        icl::utils::function - template instead. The class template is 
        specialized for member functions with less parameters.
        @see \ref FUNCTION_SECTION */
    template <class Object, class R=void, class A=NO_ARG, class B=NO_ARG, class C=NO_ARG>
    struct ConstFunctorFunctionImpl : public FunctionImpl<R, A, B, C>{
      const Object *obj;
      virtual R operator()(A a,B b, C c) const { return (*obj)(a,b,c); }
    };
    
    /** \cond **/
    template <class Object, class R, class A, class B>
    struct ConstFunctorFunctionImpl<Object, R, A, B, NO_ARG> : public FunctionImpl<R, A, B>{
      const Object *obj;
      virtual R operator()(A a,B b) const { return (*obj)(a,b); }
    };
  
    template <class Object, class R, class A>
    struct ConstFunctorFunctionImpl<Object, R, A, NO_ARG> : public FunctionImpl<R, A>{
      const Object *obj;
      virtual R operator()(A a) const { return (*obj)(a); }
    };
    template <class Object, class R>
    struct ConstFunctorFunctionImpl<Object, R, NO_ARG> : public FunctionImpl<R>{
      const Object *obj;
      virtual R operator()() const { return (*obj)(); }
    };
    /** \endcond **/
  
    //////////////////////////////////////////////////////////
    // Global Function Wrappers //////////////////////////////
    //////////////////////////////////////////////////////////
    
   
    /// FunctionImpl implementation for global functions \ingroup FUNCTION
    /** This class should not be used directly! Use the overloaded
        icl::utils::function - template instead. The class template is 
        specialized for member functions with less parameters.
        @see \ref FUNCTION_SECTION */
    template <class R=void, class A=NO_ARG, class B=NO_ARG, class C=NO_ARG>
    struct GlobalFunctionImpl : public FunctionImpl<R, A, B, C>{
      R (*global_function)(A, B, C);
      virtual R operator()(A a,B b,C c) const { return global_function(a, b,c); }
    };
    /** \cond **/
    template <class R, class A, class B>
    struct GlobalFunctionImpl<R, A, B, NO_ARG> : public FunctionImpl<R, A, B>{
      R (*global_function)(A, B);
      virtual R operator()(A a,B b) const { return global_function(a, b); }
    };
  
    template <class R, class A>
    struct GlobalFunctionImpl<R, A, NO_ARG> : public FunctionImpl<R, A>{
      R (*global_function)(A);
      virtual R operator()(A a) const { return global_function(a); }
    };
    template <class R>
    struct GlobalFunctionImpl<R, NO_ARG> : public FunctionImpl<R>{
      R (*global_function)();
      virtual R operator()() const { return global_function(); }
    };
    /** \endcond **/
    
    //////////////////////////////////////////////////////////
    // The Function class ////////////////////////////////////
    //////////////////////////////////////////////////////////
    
    /// The General Function Template \ingroup FUNCTION
    /** The Function class can be used as a generic functor that
        can have one of these backends:
        - A global function call
        - A member function call
        - A call to an objects function operator (i.e. it wrapps a functor)
        - An arbitrary implementation by wrapping a custom implementation
          of FunctionImpl<R,A,B>
        
        This class should not be used directly! Use the overloaded
        icl::utils::function - template instead. Functions can be copied
        as objects. Internally, a SmartPointer is used to manage
        the actual function implementation.
        
        The Function class template is specialized for functions 
        with less than two parameters. In this case the Function's
        function-operator() also has less parameters.
        
        @see \ref FUNCTION_SECTION */
    template<class R=void, class A=NO_ARG, class B=NO_ARG, class C=NO_ARG> 
    struct Function {
      /// Empty constructor (implementation will become null)
      Function(){}
      
      /// Constructor with given Impl
      Function(FunctionImpl<R,A,B,C> *impl):impl(impl){}
  
      /// Constructor with given SmartPtr<Impl>
      Function(icl::utils::SmartPtr<FunctionImpl<R,A,B,C> >impl):impl(impl){}
  
      /// Constructor from given global function (for implicit conversion)
      /** This constructor can be used for implicit conversion. Where
          a Function<R,A,B> is expected, you can simply pass a global
          function of type R(*function)(A,B)*/
      Function(R (*global_function)(A,B,C)):impl(new GlobalFunctionImpl<R,A,B,C>){
        ((GlobalFunctionImpl<R,A,B,C>*)(impl.get()))->global_function = global_function;
      }
      
      /// Implementation
      icl::utils::SmartPtr<FunctionImpl<R,A,B,C> >impl;
      
      /// function operator (always const)
      /** This is const, since the creator template icl::utils::function
          will automatically create the correct implementation */
      R operator()(A a, B b, C c) const { return (*impl)(a,b,c); }
      
      /// checks wheter the implemnetation is not null
      operator bool() const { return impl; }
  
      operator Function<R,A,B,C> () const { return (*(const Function<R,A,B,C>*)(this)); }
    };
    
    /** \cond */
    template<class R, class A, class B> 
    struct Function<R, A, B, NO_ARG> : public std::binary_function<A, B, R>{
      Function(){}
      Function(FunctionImpl<R,A,B> *impl):impl(impl){}
      Function(icl::utils::SmartPtr<FunctionImpl<R,A,B> >impl):impl(impl){}
      Function(R (*global_function)(A,B)):impl(new GlobalFunctionImpl<R,A,B>){
        ((GlobalFunctionImpl<R,A,B>*)(impl.get()))->global_function = global_function;
      }
      icl::utils::SmartPtr<FunctionImpl<R,A,B> >impl;
      R operator()(A a, B b) const { return (*impl)(a,b); }
      operator bool() const { return impl; }
      
      operator Function<R,A,B> () const { return (*(const Function<R,A,B>*)(this)); }
    };
  
    template<class R, class A> 
    struct Function<R, A, NO_ARG> : public std::unary_function<A, R>{
      Function(){}
      Function(FunctionImpl<R,A> *impl):impl(impl){}
      Function(icl::utils::SmartPtr<FunctionImpl<R,A> >impl):impl(impl){}
      Function(R (*global_function)(A)):impl(new GlobalFunctionImpl<R,A>){
        ((GlobalFunctionImpl<R,A>*)(impl.get()))->global_function = global_function;
      }
      icl::utils::SmartPtr<FunctionImpl<R,A> >impl;
	  R operator()(A a) const { return (*impl)(a); }
      operator bool() const { return impl; }
      
      operator Function<R,A> () const { return (*(const Function<R,A>*)(this)); }
    };
    template<class R> 
    struct Function<R, NO_ARG>{
      typedef R result_type;
      Function(){}
      Function(FunctionImpl<R> *impl):impl(impl){}
      Function(icl::utils::SmartPtr<FunctionImpl<R> >impl):impl(impl){}
      Function(R (*global_function)()):impl(new GlobalFunctionImpl<R>){
        ((GlobalFunctionImpl<R>*)(impl.get()))->global_function = global_function;
      }
	  icl::utils::SmartPtr<FunctionImpl<R> >impl;
	  R operator()() const { return (*impl)(); }
  
      operator bool() const { return impl; }
  
      operator Function<R> () const { return (*(const Function<R>*)(this)); }
    };
    /** \endcond */
        
  
  
  
    //////////////////////////////////////////////////////////
    // Function creator functions (from member functions /////
    //////////////////////////////////////////////////////////
  
    /// Create Function instances from member functions \ingroup FUNCTION
    /** This version of function allows to create a Function instance from 
        a given object instance (passed by reference) and a given binary member function
        @see \ref FUNCTION_SECTION */
    template<class Object, class R, class A, class B, class C>
    Function<R, A, B, C> function(Object &obj, R(Object::*method)(A, B, C)){
      MemberFunctionImpl<Object,R,A,B,C> *impl = new MemberFunctionImpl<Object,R,A,B,C>;
      impl->obj = &obj;
      impl->method = method;
      return Function<R,A,B,C>(impl);
    } 
    
    /// Create Function instances from member functions \ingroup FUNCTION
    /** This version of function allows to create a Function instance from 
        a given object instance (passed by reference) and a given binary member function
        @see \ref FUNCTION_SECTION */
    template<class Object,class R, class A, class B>
    Function<R, A, B> function(Object &obj, R(Object::*method)(A, B)){
      MemberFunctionImpl<Object,R,A,B> *impl = new MemberFunctionImpl<Object,R,A,B>;
      impl->obj = &obj;
      impl->method = method;
      return Function<R,A,B>(impl);
    } 
    
    /// create Function instances from member function \ingroup FUNCTION
    /** This version of function allows to create a Function instance from 
        a given object instance (passed by reference) and a given unary member function
        @see \ref FUNCTION_SECTION */
    template<class Object,class R, class A>
    Function<R, A> function(Object &obj, R(Object::*method)(A)){
      MemberFunctionImpl<Object,R,A> *impl = new MemberFunctionImpl<Object,R,A>;
      impl->obj = &obj;
      impl->method = method;
      return Function<R,A>(impl);
    } 
  
    /// create Function instances from member function \ingroup FUNCTION
    /** This version of function allows to create a Function instance from 
        a given object instance (passed by reference) and a given parameter-less
        member function
        @see \ref FUNCTION_SECTION */
    template<class Object,class R>
    Function<R> function(Object &obj, R(Object::*method)()){
      MemberFunctionImpl<Object,R> *impl = new MemberFunctionImpl<Object,R>;
      impl->obj = &obj;
      impl->method = method;
      return Function<R>(impl);
    } 
  
    /// create Function instances from const member function \ingroup FUNCTION
    /** This version of function allows to create a Function instance from 
        a given object instance (passed by reference) and a given unary member function
        @see \ref FUNCTION_SECTION */
    template<class Object,class R,class A,class B,class C>
    Function<R, A, B, C> function(const Object &obj, R(Object::*method)(A a, B b, C c) const){
      ConstMemberFunctionImpl<Object,R,A,B,C> *impl = new ConstMemberFunctionImpl<Object,R,A,B,C>;
      impl->obj = &obj;
      impl->method = method;
      return Function<R,A,B,C>(impl);
    } 
    
    /// create Function instances from const member function \ingroup FUNCTION
    /** This version of function allows to create a Function instance from 
        a given object instance (passed by reference) and a given unary member function
        @see \ref FUNCTION_SECTION */
    template<class Object,class R,class A,class B>
    Function<R, A, B> function(const Object &obj, R(Object::*method)(A a, B b) const){
      ConstMemberFunctionImpl<Object,R,A,B> *impl = new ConstMemberFunctionImpl<Object,R,A,B>;
      impl->obj = &obj;
      impl->method = method;
      return Function<R,A,B>(impl);
    } 
    /// create Function instances from const member function \ingroup FUNCTION
    /** This version of function allows to create a Function instance from 
        a given object instance (passed by reference) and a given unary member function
        @see \ref FUNCTION_SECTION */
    template<class Object,class R,class A>
    Function<R, A> function(const Object &obj, R(Object::*method)(A a) const){
      ConstMemberFunctionImpl<Object,R,A> *impl = new ConstMemberFunctionImpl<Object,R,A>;
      impl->obj = &obj;
      impl->method = method;
      return Function<R,A>(impl);
    } 
    /// create Function instances from const member function \ingroup FUNCTION
    /** This version of function allows to create a Function instance from 
        a given object instance (passed by reference) and a given parameter-less
        member function
        @see \ref FUNCTION_SECTION */
    template<class Object,class R>
    Function<R> function(const Object &obj, R(Object::*method)() const){
      ConstMemberFunctionImpl<Object,R> *impl = new ConstMemberFunctionImpl<Object,R>;
      impl->obj = &obj;
      impl->method = method;
      return Function<R>(impl);
    } 
  
    /// Create Function instances from member functions \ingroup FUNCTION
    /** This version of function allows to create a Function instance from 
        a given object instance (passed by reference) and a given binary member function
        @see \ref FUNCTION_SECTION */
    template<class Object,class R, class A, class B, class C>
    Function<R, A, B, C> function(Object *obj, R(Object::*method)(A, B, C)){ return function<Object, R, A, B, C>(*obj, method); }
  
    /// Create Function instances from member functions \ingroup FUNCTION
    /** This version of function allows to create a Function instance from 
        a given object instance (passed by reference) and a given binary member function
        @see \ref FUNCTION_SECTION */
    template<class Object,class R, class A, class B>
    Function<R, A, B> function(Object *obj, R(Object::*method)(A, B)){ return function<Object, R, A, B>(*obj, method); }
    
    /// create Function instances from member function \ingroup FUNCTION
    /** This version of function allows to create a Function instance from 
        a given object instance (passed by reference) and a given unary member function
        @see \ref FUNCTION_SECTION */
    template<class Object,class R, class A>
    Function<R, A> function(Object *obj, R(Object::*method)(A)){ return function<Object, R, A>(*obj, method); }
    
    /// create Function instances from member function \ingroup FUNCTION
    /** This version of function allows to create a Function instance from 
        a given object instance (passed by reference) and a given parameter-less
        member function
        @see \ref FUNCTION_SECTION */
    template<class Object,class R>
    Function<R> function(Object *obj, R(Object::*method)()){ return function<Object, R>(*obj, method); }
  
    /// Create Function instances from const member functions \ingroup FUNCTION
    /** This version of function allows to create a Function instance from 
        a given object instance (passed by reference) and a given binary member function
        @see \ref FUNCTION_SECTION */ 
    template<class Object,class R, class A, class B, class C>
    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); }
   
    /// Create Function instances from const member functions \ingroup FUNCTION
    /** This version of function allows to create a Function instance from 
        a given object instance (passed by reference) and a given binary member function
        @see \ref FUNCTION_SECTION */ 
    template<class Object,class R, class A, class B>
    Function<R, A, B> function(const Object *obj, R(Object::*method)(A, B) const){ return function<Object, R, A, B>(*obj, method); }
  
    /// create Function instances from const member function \ingroup FUNCTION
    /** This version of function allows to create a Function instance from 
        a given object instance (passed by reference) and a given unary member function
        @see \ref FUNCTION_SECTION */
    template<class Object,class R, class A>
    Function<R, A> function(const Object *obj, R(Object::*method)(A) const){ return function<Object, R, A>(*obj, method); }
    
    /// create Function instances from const member function \ingroup FUNCTION
    /** This version of function allows to create a Function instance from 
        a given object instance (passed by reference) and a given parameter-less
        member function
        @see \ref FUNCTION_SECTION */
    template<class Object,class R>
    Function<R> function(const Object *obj, R(Object::*method)() const){ return function<Object, R>(*obj, method); }
  
    
    //////////////////////////////////////////////////////////
    // Function creator functions (from functors) ////////////
    //////////////////////////////////////////////////////////
    
    /// Empty utility template that can be used to select a special functor \ingroup FUNCTION
    /** @see \ref FUNCTION_SECTION */
    template <class R = void, class A = NO_ARG, class B = NO_ARG, class C = NO_ARG> struct SelectFunctor{};
    
    /// create Function instances from given object-functor \ingroup FUNCTION
    /** In constrast to functions, a pointer to an objects overloaded functor can only
        be defined hardly. Therefore this version of the icl::utils::function-template allows
        to pick a functor from a given object 
        @see \ref FUNCTION_SECTION */
    template<class Object,class R, class A, class B, class C>
    Function<R, A, B, C> function(Object &obj, SelectFunctor<R, A, B, C>){
      FunctorFunctionImpl<Object,R,A,B,C>  *impl = new FunctorFunctionImpl<Object,R,A,B,C>;
      impl->obj = &obj;
      return Function<R,A,B,C>(impl);
    } 
  
    /// create Function instances from given object-functor (const version) \ingroup FUNCTION
    /** In constrast to functions, a pointer to an objects overloaded functor can only
        be defined hardly. Therefore this version of the icl::utils::function-template allows
        to pick a functor from a given object 
        @see \ref FUNCTION_SECTION */
    template<class Object,class R, class A, class B, class C>
    Function<R, A, B> function(const Object &obj, SelectFunctor<R, A, B, C>){
      ConstFunctorFunctionImpl<Object,R,A,B,C>  *impl = new ConstFunctorFunctionImpl<Object,R,A,B,C>;
      impl->obj = &obj;
      return Function<R,A,B,C>(impl);
    } 
  
    /// shortcut create Function to wrap an objects parameter-less function operator \ingroup FUNCTION
    /** @see \ref FUNCTION_SECTION */
    template<class Object>
    Function<> function(Object &obj){
      return function(obj,SelectFunctor<void,NO_ARG,NO_ARG,NO_ARG>());
    } 
  
    /// shortcut create Function to wrap a const objects parameter-less function operator \ingroup FUNCTION
    /** @see \ref FUNCTION_SECTION */
    template<class Object>
    Function<> function(const Object &obj){
      return function(obj,SelectFunctor<void,NO_ARG,NO_ARG,NO_ARG>());
    } 
  
    /// create Function instances from given object-functor \ingroup FUNCTION
    /** In constrast to functions, a pointer to an objects overloaded functor can only
        be defined hardly. Therefore this version of the icl::utils::function-template allows
        to pick a functor from a given object 
        @see \ref FUNCTION_SECTION */
    template<class Object,class R, class A, class B, class C>
    Function<R, A, B, C> function(Object *obj, SelectFunctor<R, A, B, C> selector){ return function<Object, R, A, B, C>(*obj, selector); }
    
   /// create Function instances from given object-functor (const version) \ingroup FUNCTION
    /** In constrast to functions, a pointer to an objects overloaded functor can only
        be defined hardly. Therefore this version of the icl::utils::function-template allows
        to pick a functor from a given object 
        @see \ref FUNCTION_SECTION */
    template<class Object,class R, class A, class B, class C>
    Function<R, A, B, C> function(const Object *obj, SelectFunctor<R, A, B, C> selector){ return function<Object, R, A, B, C>(*obj, selector); }
    
    
    //////////////////////////////////////////////////////////
    // Function creator functions (from global functions) ////
    //////////////////////////////////////////////////////////
  
    /// Function creator function from given binary global function \ingroup FUNCTION
    /** In contrast to the constructor, this method can automatically
        detect the parameter types (like std::make_pair)
        @see \ref FUNCTION_SECTION */
    template<class R, class A, class B, class C>
    Function<R, A, B, C> function(R(*global_function)(A a, B b, C c)){
      return Function<R,A,B,C>(global_function);
    } 
    
    /// Function creator function from given binary global function \ingroup FUNCTION
    /** In contrast to the constructor, this method can automatically
        detect the parameter types (like std::make_pair)
        @see \ref FUNCTION_SECTION */
    template<class R, class A, class B>
    Function<R, A, B> function(R(*global_function)(A a, B b)){
      return Function<R,A,B>(global_function);
    } 
  
    
    /// Function creator function from given unary global function \ingroup FUNCTION
    /** In contrast to the constructor, this method can automatically
        detect the parameter types (like std::make_pair)
        @see \ref FUNCTION_SECTION */
    template<class R, class A>
    Function<R, A> function(R(*global_function)(A a)){
      return Function<R,A>(global_function);
    } 
  
    /// Function creator function from given parameter less global function \ingroup FUNCTION
    /** In contrast to the constructor, this method can automatically
        detect the parameter types (like std::make_pair)
        @see \ref FUNCTION_SECTION */
    template<class R>
    Function<R> function(R(*global_function)()){
      return Function<R>(global_function);
    }
  } // namespace utils
}