dnl Copyright 2002, The libsigc++ Development Team dnl dnl This library is free software; you can redistribute it and/or dnl modify it under the terms of the GNU Lesser General Public dnl License as published by the Free Software Foundation; either dnl version 2.1 of the License, or (at your option) any later version. dnl dnl This library is distributed in the hope that it will be useful, dnl but WITHOUT ANY WARRANTY; without even the implied warranty of dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU dnl Lesser General Public License for more details. dnl dnl You should have received a copy of the GNU Lesser General Public dnl License along with this library; if not, write to the Free Software dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA dnl divert(-1) include(template.macros.m4) dnl dnl The idea here is simple. To prevent the need to dnl specializing every adaptor for every type of functor dnl and worse non-functors like function pointers, we dnl will make an adaptor trait which can take ordinary dnl functors and make them adaptor functors for which dnl we will of course be able to avoid excess copies. dnl (in theory) dnl dnl this all depends on partial specialization to allow dnl us to do dnl functor_.template operator() (args); dnl dnl I don't understand much of the above. However, I can dnl see that adaptors are implemented like they are because dnl there is no way to extract the return type and the argument dnl types from a functor type. Therefore, operator() is templated. dnl It's instatiated in slot_call#<>::operator() where the dnl argument types are known. The return type is finally determined dnl via the callof<> template - a tricky way to detect the return dnl type of a functor when the argument types are known. Martin. ]) define([ADAPTOR_DO],[dnl ifelse($1,0,[dnl dnl typename internal::callof_safe0::result_type // doesn't compile if T_functor has an overloaded operator()! dnl typename functor_trait::result_type dnl operator()() const dnl { return functor_(); } ],[dnl /** Invokes the wrapped functor passing on the arguments.dnl FOR(1, $1,[ * @param _A_arg%1 Argument to be passed on to the functor.]) * @return The return value of the functor invocation. */ template typename deduce_result_type::type operator()(LOOP(T_arg%1 _A_arg%1, $1)) const { return functor_(LOOP(_A_arg%1, $1)); } #ifndef SIGC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD template typename deduce_result_type::type sun_forte_workaround(LOOP(T_arg%1 _A_arg%1, $1)) const { //Just calling operator() tries to copy the argument: return functor_(LOOP(_A_arg%1, $1)); } #endif ])dnl ]) divert(0)dnl _FIREWALL([ADAPTORS_ADAPTOR_TRAIT]) #include //To get SIGC_TEMPLATE_KEYWORD_OPERATOR_OVERLOAD #include #include #include #include #include namespace sigc { // Call either operator()<>() or sun_forte_workaround<>(), // depending on the compiler: #ifdef SIGC_GCC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD #define SIGC_WORKAROUND_OPERATOR_PARENTHESES template operator() #define SIGC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD #else #ifdef SIGC_MSVC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD #define SIGC_WORKAROUND_OPERATOR_PARENTHESES operator() #define SIGC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD #else #define SIGC_WORKAROUND_OPERATOR_PARENTHESES sun_forte_workaround #endif #endif #ifndef DOXYGEN_SHOULD_SKIP_THIS template struct adapts; #endif /** @defgroup adaptors Adaptors * Adaptors are functors that alter the signature of a functor's * operator()(). * * The adaptor types libsigc++ provides * are created with bind(), bind_return(), hide(), hide_return(), * retype_return(), retype(), compose(), exception_catch(), track_obj() * and group(). * * You can easily derive your own adaptor type from sigc::adapts. */ /** Converts an arbitrary functor into an adaptor type. * All adaptor types in libsigc++ have * a template operator() member of every argument count * they support. These functions in turn invoke a stored adaptor's * template operator(), processing the arguments and return * value in a characteristic manner. Explicit function template * instantiation is used to pass type hints thus saving copy costs. * * adaptor_functor is a glue between adaptors and arbitrary functors * that just passes on the arguments. You won't use this type directly. * * The template argument @e T_functor determines the type of stored * functor. * * @ingroup adaptors */ template struct adaptor_functor : public adaptor_base { #ifndef DOXYGEN_SHOULD_SKIP_THIS template struct deduce_result_type { typedef sigc::deduce_result_t type; }; #endif typedef typename functor_trait::result_type result_type; /** Invokes the wrapped functor passing on the arguments. * @return The return value of the functor invocation. */ result_type operator()() const; #ifndef SIGC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD result_type sun_forte_workaround() const { return operator(); } #endif FOR(0,CALL_SIZE,[[ADAPTOR_DO(%1)]])dnl /// Constructs an invalid functor. adaptor_functor() {} /** Constructs an adaptor_functor object that wraps the passed functor. * @param _A_functor Functor to invoke from operator()(). */ explicit adaptor_functor(const T_functor& _A_functor) : functor_(_A_functor) {} /** Constructs an adaptor_functor object that wraps the passed (member) * function pointer. * @param _A_type Pointer to function or class method to invoke from operator()(). */ template explicit adaptor_functor(const T_type& _A_type) : functor_(_A_type) {} /// Functor that is invoked from operator()(). mutable T_functor functor_; }; template typename adaptor_functor::result_type adaptor_functor::operator()() const { return functor_(); } #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::adaptor_functor performs a functor * on the functor stored in the sigc::adaptor_functor object. * * @ingroup adaptors */ template struct visitor > { template static void do_visit_each(const T_action& _A_action, const adaptor_functor& _A_target) { sigc::visit_each(_A_action, _A_target.functor_); } }; #endif // DOXYGEN_SHOULD_SKIP_THIS /** Trait that specifies what is the adaptor version of a functor type. * Template specializations for sigc::adaptor_base derived functors, * for function pointers and for class methods are provided. * * The template argument @e T_functor is the functor type to convert. * @e I_isadaptor indicates whether @e T_functor inherits from sigc::adaptor_base. * * @ingroup adaptors */ #ifndef DOXYGEN_SHOULD_SKIP_THIS template ::value> struct adaptor_trait; #else template ::value> struct adaptor_trait {}; #endif /** Trait that specifies what is the adaptor version of a functor type. * This template specialization is used for types that inherit from adaptor_base. * adaptor_type is equal to @p T_functor in this case. */ template struct adaptor_trait { typedef typename T_functor::result_type result_type; typedef T_functor functor_type; typedef T_functor adaptor_type; }; /** Trait that specifies what is the adaptor version of a functor type. * This template specialization is used for arbitrary functors, * for function pointers and for class methods are provided. * The latter are converted into @p pointer_functor or @p mem_functor types. * adaptor_type is equal to @p adaptor_functor. */ template struct adaptor_trait { typedef typename functor_trait::result_type result_type; typedef typename functor_trait::functor_type functor_type; typedef adaptor_functor adaptor_type; }; // Doxygen (at least version 1.8.4) removes blank lines in a code block. // That's why there are empty comment lines in the following code block. /** Base type for adaptors. * sigc::adapts wraps adaptors, functors, function pointers and class methods. * It contains a single member functor which is always a sigc::adaptor_base. * The typedef adaptor_type defines the exact type that is used * to store the adaptor, functor, function pointer or class method passed * into the constructor. It differs from @a T_functor unless @a T_functor * inherits from sigc::adaptor_base. * * @par Example of a simple adaptor: * @code * namespace my_ns * { * template * struct my_adaptor : public sigc::adapts * { * template * struct deduce_result_type * { typedef sigc::deduce_result_t type; }; * typedef typename sigc::functor_trait::result_type result_type; * // * result_type * operator()() const; * // * template * typename deduce_result_type::type * operator()(T_arg1 _A_arg1) const; * // * template * typename deduce_result_type::type * operator()(T_arg1 _A_arg1, T_arg2 _A_arg2) const; * // * // Constructs a my_adaptor object that wraps the passed functor. * // Initializes adapts::functor_, which is invoked from operator()(). * explicit my_adaptor(const T_functor& _A_functor) * : sigc::adapts(_A_functor) {} * }; * } // end namespace my_ns * // * // Specialization of sigc::visitor for my_adaptor. * namespace sigc * { * template * struct visitor > * { * template * static void do_visit_each(const T_action& _A_action, * const my_ns::my_adaptor& _A_target) * { * sigc::visit_each(_A_action, _A_target.functor_); * } * }; * } // end namespace sigc * @endcode * * If you implement your own adaptor, you must also provide your specialization * of sigc::visitor<>::do_visit_each<>() that will forward the call to the functor(s) * your adapter is wrapping. Otherwise, pointers stored within the functor won't be * invalidated when a sigc::trackable object is destroyed and you can end up * executing callbacks on destroyed objects. * * Your specialization of sigc::visitor<> must be in namespace sigc. * * @ingroup adaptors */ template struct adapts : public adaptor_base { typedef typename adaptor_trait::result_type result_type; typedef typename adaptor_trait::adaptor_type adaptor_type; /** Constructs an adaptor that wraps the passed functor. * @param _A_functor Functor to invoke from operator()(). */ explicit adapts(const T_functor& _A_functor) : functor_(_A_functor) {} /// Adaptor that is invoked from operator()(). mutable adaptor_type functor_; }; } /* namespace sigc */