/* * 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_ADAPTORS_ADAPTOR_TRAIT_H #define SIGC_ADAPTORS_ADAPTOR_TRAIT_H #include //To get SIGC_TEMPLATE_KEYWORD_OPERATOR_OVERLOAD #include #include #include #include #include #include /* * The idea here is simple. To prevent the need to * specializing every adaptor for every type of functor * and worse non-functors like function pointers, we * will make an adaptor trait which can take ordinary * functors and make them adaptor functors for which * we will of course be able to avoid excess copies. * (in theory) * * this all depends on partial specialization to allow * us to do * functor_.template operator() (args); * * * I don't understand much of the above. However, I can * see that adaptors are implemented like they are because * there is no way to extract the return type and the argument * types from a functor type. Therefore, operator() is templated. * It's instantiated in slot_call#<>::operator() where the * argument types are known. The return type is finally determined * via the callof<> template - a tricky way to detect the return * type of a functor when the argument types are known. Martin. */ namespace sigc { /** @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 { /** Invokes the wrapped functor passing on the arguments. * @return The return value of the functor invocation. */ decltype(auto) operator()() const { return functor_(); } /** Invokes the wrapped functor passing on the arguments. * @param arg Arguments to be passed on to the functor. * @return The return value of the functor invocation. */ template decltype(auto) operator()(T_arg&&... arg) const { return std::invoke(functor_, std::forward(arg)...); } /// Constructs an invalid functor. adaptor_functor() = default; /** Constructs an adaptor_functor object that wraps the passed functor. * @param functor Functor to invoke from operator()(). */ explicit adaptor_functor(const T_functor& functor) : functor_(functor) {} /** Constructs an adaptor_functor object that wraps the passed (member) * function pointer. * @param type Pointer to function or class method to invoke from operator()(). */ template explicit adaptor_functor(const T_type& type) : functor_(type) { } /// Functor that is invoked from operator()(). mutable T_functor 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& action, const adaptor_functor& target) { sigc::visit_each(action, target.functor_); } }; #endif // DOXYGEN_SHOULD_SKIP_THIS /** Trait that specifies what is the adaptor version of a functor type. * Template specializations exist for sigc::adaptor_base-derived functors, * for function pointers and for class methods. * * 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 */ template::value> struct adaptor_trait; /** Trait that specifies 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 { using adaptor_type = T_functor; }; /** Trait that specifies the adaptor version of a functor type. * This template specialization is used for arbitrary functors, * for function pointers and for class methods. * 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 { private: using functor_type = typename functor_trait::functor_type; public: using adaptor_type = adaptor_functor; }; } /* namespace sigc */ #endif /* SIGC_ADAPTORS_ADAPTOR_TRAIT_H */