/* * Copyright 2003 - 2016, The libsigc++ Development Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef SIGC_FUNCTORS_MEM_FUN_H #define SIGC_FUNCTORS_MEM_FUN_H #include #include #include #include #include // implementation notes: // - we do not use bind here, because it would introduce // an extra copy and complicate the header include order if bind is // to have automatic conversion for member pointers. namespace sigc { /** @defgroup mem_fun mem_fun() * %mem_fun() creates a functor from a pointer to a method. * * Optionally, a reference to an object can be bound to the functor. * * @note If the object type inherits from sigc::trackable, and the * functor returned from %mem_fun() is assigned to * a @ref sigc::slot "sigc::slot", the functor * will be automatically cleared when the object goes out of scope. Invoking * that slot will then have no effect and will not try to use the destroyed * instance. * * @par Example: * @code * struct foo : public sigc::trackable * { * void bar(int) {} * }; * foo my_foo; * sigc::slot sl = sigc::mem_fun(my_foo, &foo::bar); * // Note: f is not a slot. It will not be invalidated when my_foo is deleted. * auto f = sigc::mem_fun(my_foo, &foo::bar); // Usually not what you want. * @endcode * * For const methods %mem_fun() takes a const reference or pointer to an object. * * @par Example: * @code * struct foo : public sigc::trackable * { * void bar(int) const {} * }; * const foo my_foo; * sigc::slot sl = sigc::mem_fun(my_foo, &foo::bar); * @endcode * * If the member function pointer is to an overloaded type, you must specify * the types using template arguments. * * @par Example: * @code * struct foo : public sigc::trackable * { * void bar(int) {} // choose this one * void bar(float) {} * void bar(int, int) {} * }; * foo my_foo; * sigc::slot sl = sigc::mem_fun1(my_foo, &foo::bar); * @endcode * * @ingroup sigcfunctors */ template class mem_functor { public: using object_type = typename internal::member_method_class::type; using function_type = T_func; using obj_type_with_modifier = typename std:: conditional_t::value, const object_type, object_type>; /// Constructs an invalid functor. mem_functor() : func_ptr_(nullptr) {} /** Constructs a mem_functor object that wraps the passed method. * @param func Pointer to method will be invoked from operator()(). */ explicit mem_functor(function_type func) : func_ptr_(func) {} /** Execute the wrapped method operating on the passed instance. * @param obj Reference to instance the method should operate on. * @param a Arguments to be passed on to the method. * @return The return value of the method invocation. */ decltype(auto) operator()(obj_type_with_modifier& obj, type_trait_take_t... a) const { return std::invoke(func_ptr_, obj, std::forward>(a)...); } protected: function_type func_ptr_; }; template class bound_mem_functor : mem_functor { using base_type = mem_functor; public: using function_type = typename base_type::function_type; using object_type = typename base_type::object_type; using obj_type_with_modifier = typename std:: conditional_t::value, const object_type, object_type>; using T_limit_reference = typename std::conditional_t::value, limit_reference, limit_reference>; /** Constructs a bound_mem_functor object that wraps the passed method. * @param obj Reference to instance the method will operate on. * @param func Pointer to method will be invoked from operator()(). */ bound_mem_functor(obj_type_with_modifier& obj, function_type func) : base_type(func), obj_(obj) {} /** Execute the wrapped method operating on the stored instance. * @param a Arguments to be passed on to the method. * @return The return value of the method invocation. */ decltype(auto) operator()(type_trait_take_t... a) const { return std::invoke( this->func_ptr_, obj_.invoke(), std::forward>(a)...); } // protected: // Reference to stored object instance. // This is the handler object, such as TheObject in void TheObject::signal_handler(). T_limit_reference obj_; }; #ifndef DOXYGEN_SHOULD_SKIP_THIS // template specialization of visitor<>::do_visit_each<>(action, functor): /** Performs a functor on each of the targets of a functor. * The function overload for sigc::bound_$1mem_functor performs a functor * on the object instance stored in the sigc::bound_$1mem_functor object. * * @ingroup mem_fun */ template struct visitor> { template static void do_visit_each(const T_action& action, const bound_mem_functor& target) { sigc::visit_each(action, target.obj_); } }; #endif // DOXYGEN_SHOULD_SKIP_THIS /** Creates a functor of type sigc::mem_functor which wraps a method. * @param func Pointer to method that should be wrapped. * @return Functor that executes func on invocation. * * @ingroup mem_fun */ template inline decltype(auto) mem_fun(T_return (T_obj::*func)(T_arg...)) { return mem_functor(func); } /** Creates a functor of type sigc::const_mem_functor which wraps a const method. * @param func Pointer to method that should be wrapped. * @return Functor that executes func on invocation. * * @ingroup mem_fun */ template inline decltype(auto) mem_fun(T_return (T_obj::*func)(T_arg...) const) { return mem_functor(func); } /** Creates a functor of type sigc::volatile_mem_functor which wraps a volatile method. * @param func Pointer to method that should be wrapped. * @return Functor that executes func on invocation. * * @ingroup mem_fun */ template inline decltype(auto) mem_fun(T_return (T_obj::*func)(T_arg...) volatile) { return mem_functor(func); } /** Creates a functor of type sigc::const_volatile_mem_functor which wraps a const volatile method. * @param func Pointer to method that should be wrapped. * @return Functor that executes func on invocation. * * @ingroup mem_fun */ template inline decltype(auto) mem_fun(T_return (T_obj::*func)(T_arg...) const volatile) { return mem_functor(func); } /** Creates a functor of type sigc::bound_mem_functor which encapsulates a method and an object * instance. * @param obj Reference to object instance the functor should operate on. * @param func Pointer to method that should be wrapped. * @return Functor that executes @e func on invocation. * * @ingroup mem_fun */ template inline decltype(auto) mem_fun(/**/ T_obj& obj, T_return (T_obj2::*func)(T_arg...)) { return bound_mem_functor(obj, func); } /** Creates a functor of type sigc::bound_const_mem_functor which encapsulates a method and an * object instance. * @param obj Reference to object instance the functor should operate on. * @param func Pointer to method that should be wrapped. * @return Functor that executes @e func on invocation. * * @ingroup mem_fun */ template inline decltype(auto) mem_fun(/*const*/ T_obj& obj, T_return (T_obj2::*func)(T_arg...) const) { return bound_mem_functor(obj, func); } /** Creates a functor of type sigc::bound_volatile_mem_functor which encapsulates a method and an * object instance. * @param obj Reference to object instance the functor should operate on. * @param func Pointer to method that should be wrapped. * @return Functor that executes @e func on invocation. * * @ingroup mem_fun */ template inline decltype(auto) mem_fun(/**/ T_obj& obj, T_return (T_obj2::*func)(T_arg...) volatile) { return bound_mem_functor(obj, func); } /** Creates a functor of type sigc::bound_const_volatile_mem_functor which encapsulates a method and * an object instance. * @param obj Reference to object instance the functor should operate on. * @param func Pointer to method that should be wrapped. * @return Functor that executes @e func on invocation. * * @ingroup mem_fun */ template inline decltype(auto) mem_fun(/*const*/ T_obj& obj, T_return (T_obj2::*func)(T_arg...) const volatile) { return bound_mem_functor(obj, func); } } /* namespace sigc */ #endif /* SIGC_FUNCTORS_MEM_FUN_H */