/******************************************************************** ** 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 #include #include namespace icl{ namespace utils{ struct NO_ARG; ///////////////////////////////////////////////////////// // FunctionImpl classes and specializations ///////////// ///////////////////////////////////////////////////////// /// General Implementation for binary functions \ingroup FUNCTION /** @see \ref FUNCTION_SECTION */ template 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 struct FunctionImpl{ /// 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 struct FunctionImpl{ /// function interface virtual R operator()(A a) const = 0; virtual ~FunctionImpl(){} }; /// Special Implementation for void functions \ingroup FUNCTION /** @see \ref FUNCTION_SECTION */ template struct FunctionImpl{ /// 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 struct MemberFunctionImpl : public FunctionImpl{ 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 struct MemberFunctionImpl : public FunctionImpl{ Object *obj; R (Object::*method)(A, B); virtual R operator()(A a,B b) const { return (obj->*method)(a, b); } }; template struct MemberFunctionImpl : public FunctionImpl{ Object *obj; R (Object::*method)(A); virtual R operator()(A a) const { return (obj->*method)(a); } }; template struct MemberFunctionImpl : public FunctionImpl{ 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 struct ConstMemberFunctionImpl : public FunctionImpl{ 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 struct ConstMemberFunctionImpl : public FunctionImpl{ const Object *obj; R (Object::*method)(A, B) const; virtual R operator()(A a,B b) const { return (obj->*method)(a, b); } }; template struct ConstMemberFunctionImpl : public FunctionImpl{ const Object *obj; R (Object::*method)(A) const; virtual R operator()(A a) const { return (obj->*method)(a); } }; template struct ConstMemberFunctionImpl : public FunctionImpl{ 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 struct FunctorFunctionImpl : public FunctionImpl{ Object *obj; virtual R operator()(A a,B b, C c) const { return (*obj)(a,b,c); } }; /** \cond **/ template struct FunctorFunctionImpl : public FunctionImpl{ Object *obj; virtual R operator()(A a,B b) const { return (*obj)(a,b); } }; template struct FunctorFunctionImpl : public FunctionImpl{ Object *obj; virtual R operator()(A a) const { return (*obj)(a); } }; template struct FunctorFunctionImpl : public FunctionImpl{ 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 struct ConstFunctorFunctionImpl : public FunctionImpl{ const Object *obj; virtual R operator()(A a,B b, C c) const { return (*obj)(a,b,c); } }; /** \cond **/ template struct ConstFunctorFunctionImpl : public FunctionImpl{ const Object *obj; virtual R operator()(A a,B b) const { return (*obj)(a,b); } }; template struct ConstFunctorFunctionImpl : public FunctionImpl{ const Object *obj; virtual R operator()(A a) const { return (*obj)(a); } }; template struct ConstFunctorFunctionImpl : public FunctionImpl{ 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 struct GlobalFunctionImpl : public FunctionImpl{ R (*global_function)(A, B, C); virtual R operator()(A a,B b,C c) const { return global_function(a, b,c); } }; /** \cond **/ template struct GlobalFunctionImpl : public FunctionImpl{ R (*global_function)(A, B); virtual R operator()(A a,B b) const { return global_function(a, b); } }; template struct GlobalFunctionImpl : public FunctionImpl{ R (*global_function)(A); virtual R operator()(A a) const { return global_function(a); } }; template struct GlobalFunctionImpl : public FunctionImpl{ 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 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 struct Function { /// Empty constructor (implementation will become null) Function(){} /// Constructor with given Impl Function(FunctionImpl *impl):impl(impl){} /// Constructor with given SmartPtr Function(icl::utils::SmartPtr >impl):impl(impl){} /// Constructor from given global function (for implicit conversion) /** This constructor can be used for implicit conversion. Where a Function 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){ ((GlobalFunctionImpl*)(impl.get()))->global_function = global_function; } /// Implementation icl::utils::SmartPtr >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 () const { return (*(const Function*)(this)); } }; /** \cond */ template struct Function : public std::binary_function{ Function(){} Function(FunctionImpl *impl):impl(impl){} Function(icl::utils::SmartPtr >impl):impl(impl){} Function(R (*global_function)(A,B)):impl(new GlobalFunctionImpl){ ((GlobalFunctionImpl*)(impl.get()))->global_function = global_function; } icl::utils::SmartPtr >impl; R operator()(A a, B b) const { return (*impl)(a,b); } operator bool() const { return impl; } operator Function () const { return (*(const Function*)(this)); } }; template struct Function : public std::unary_function{ Function(){} Function(FunctionImpl *impl):impl(impl){} Function(icl::utils::SmartPtr >impl):impl(impl){} Function(R (*global_function)(A)):impl(new GlobalFunctionImpl){ ((GlobalFunctionImpl*)(impl.get()))->global_function = global_function; } icl::utils::SmartPtr >impl; R operator()(A a) const { return (*impl)(a); } operator bool() const { return impl; } operator Function () const { return (*(const Function*)(this)); } }; template struct Function{ typedef R result_type; Function(){} Function(FunctionImpl *impl):impl(impl){} Function(icl::utils::SmartPtr >impl):impl(impl){} Function(R (*global_function)()):impl(new GlobalFunctionImpl){ ((GlobalFunctionImpl*)(impl.get()))->global_function = global_function; } icl::utils::SmartPtr >impl; R operator()() const { return (*impl)(); } operator bool() const { return impl; } operator Function () const { return (*(const Function*)(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 Function function(Object &obj, R(Object::*method)(A, B, C)){ MemberFunctionImpl *impl = new MemberFunctionImpl; impl->obj = &obj; impl->method = method; return Function(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 Function function(Object &obj, R(Object::*method)(A, B)){ MemberFunctionImpl *impl = new MemberFunctionImpl; impl->obj = &obj; impl->method = method; return Function(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 Function function(Object &obj, R(Object::*method)(A)){ MemberFunctionImpl *impl = new MemberFunctionImpl; impl->obj = &obj; impl->method = method; return Function(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 Function function(Object &obj, R(Object::*method)()){ MemberFunctionImpl *impl = new MemberFunctionImpl; impl->obj = &obj; impl->method = method; return Function(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 Function function(const Object &obj, R(Object::*method)(A a, B b, C c) const){ ConstMemberFunctionImpl *impl = new ConstMemberFunctionImpl; impl->obj = &obj; impl->method = method; return Function(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 Function function(const Object &obj, R(Object::*method)(A a, B b) const){ ConstMemberFunctionImpl *impl = new ConstMemberFunctionImpl; impl->obj = &obj; impl->method = method; return Function(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 Function function(const Object &obj, R(Object::*method)(A a) const){ ConstMemberFunctionImpl *impl = new ConstMemberFunctionImpl; impl->obj = &obj; impl->method = method; return Function(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 Function function(const Object &obj, R(Object::*method)() const){ ConstMemberFunctionImpl *impl = new ConstMemberFunctionImpl; impl->obj = &obj; impl->method = method; return Function(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 Function function(Object *obj, R(Object::*method)(A, B, C)){ return function(*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 Function function(Object *obj, R(Object::*method)(A, B)){ return function(*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 Function function(Object *obj, R(Object::*method)(A)){ return function(*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 Function function(Object *obj, R(Object::*method)()){ return function(*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 Function function(const Object *obj, R(Object::*method)(A, B, C) const){ return function(*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 Function function(const Object *obj, R(Object::*method)(A, B) const){ return function(*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 Function function(const Object *obj, R(Object::*method)(A) const){ return function(*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 Function function(const Object *obj, R(Object::*method)() const){ return function(*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 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 Function function(Object &obj, SelectFunctor){ FunctorFunctionImpl *impl = new FunctorFunctionImpl; impl->obj = &obj; return Function(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 Function function(const Object &obj, SelectFunctor){ ConstFunctorFunctionImpl *impl = new ConstFunctorFunctionImpl; impl->obj = &obj; return Function(impl); } /// shortcut create Function to wrap an objects parameter-less function operator \ingroup FUNCTION /** @see \ref FUNCTION_SECTION */ template Function<> function(Object &obj){ return function(obj,SelectFunctor()); } /// shortcut create Function to wrap a const objects parameter-less function operator \ingroup FUNCTION /** @see \ref FUNCTION_SECTION */ template Function<> function(const Object &obj){ return function(obj,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 Function function(Object *obj, SelectFunctor selector){ return function(*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 Function function(const Object *obj, SelectFunctor selector){ return function(*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 Function function(R(*global_function)(A a, B b, C c)){ return Function(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 Function function(R(*global_function)(A a, B b)){ return Function(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 Function function(R(*global_function)(A a)){ return Function(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 Function function(R(*global_function)()){ return Function(global_function); } } // namespace utils }