1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
|
/*
* Copyright 2013 - 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_TRACK_OBJ_H
#define SIGC_ADAPTORS_TRACK_OBJ_H
#include <sigc++/adaptors/adapts.h>
#include <sigc++/adaptors/tuple_visitor_visit_each.h>
#include <sigc++/limit_reference.h>
#include <sigc++/tuple-utils/tuple_for_each.h>
#include <sigc++/trackable.h>
#include <type_traits>
#include <algorithm>
namespace sigc
{
/** @defgroup track_obj track_obj(), track_object()
* sigc::track_object() tracks trackable objects, referenced from a functor.
* It can be useful when you assign a C++11 lambda expression or a std::function<>
* to a slot, or connect it to a signal, and the lambda expression or std::function<>
* contains references to sigc::trackable derived objects.
*
* The functor returned by sigc::track_object() is formally an adaptor, but it does
* not alter the signature, return type or behaviour of the supplied functor.
*
* track_obj() is a deprecated alternative to track_object().
*
* @par Example:
* @code
* struct bar : public sigc::trackable {};
* sigc::signal<void()> some_signal;
* void foo(bar&);
* {
* bar some_bar;
* some_signal.connect([&some_bar](){ foo(some_bar); });
* // NOT disconnected automatically when some_bar goes out of scope
* some_signal.connect(sigc::track_object([&some_bar](){ foo(some_bar); }, some_bar);
* // disconnected automatically when some_bar goes out of scope
* }
* @endcode
*
* @ingroup adaptors
*/
/** %track_obj_functor wraps a functor and stores a reference to a trackable object.
* Use the convenience function track_object() to create an instance of %track_obj_functor.
*
* track_obj() is a deprecated alternative to track_object().
*
* @tparam T_functor The type of functor to wrap.
* @tparam T_obj The types of the trackable objects.
*
* @newin{2,4}
*
* @ingroup track_obj
*/
template<typename T_functor, typename... T_obj>
class track_obj_functor : public adapts<T_functor>
{
public:
/** Constructs a track_obj_functor object that wraps the passed functor and
* stores a reference to the passed trackable objects.
* @param func Functor.
* @param obj Trackable objects.
*/
explicit track_obj_functor(const T_functor& func, const T_obj&... obj)
: adapts<T_functor>(func), obj_(obj...)
{
}
/** 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<typename... T_arg>
decltype(auto) operator()(T_arg&&... arg)
{
return std::invoke(this->functor_, std::forward<T_arg>(arg)...);
}
#ifndef DOXYGEN_SHOULD_SKIP_THIS
// protected:
// public, so that visit_each() can access it.
std::tuple<limit_reference<const T_obj>...> obj_;
#endif /* DOXYGEN_SHOULD_SKIP_THIS */
}; // end class track_obj_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::track_obj_functor performs a functor
* on the functor and on the trackable object instances stored in the
* sigc::track_obj_functor object.
*
* @newin{2,4}
*
* @ingroup track_obj
*/
template<typename T_functor, typename... T_obj>
struct visitor<track_obj_functor<T_functor, T_obj...>>
{
template<typename T_action>
static void do_visit_each(const T_action& action,
const track_obj_functor<T_functor, T_obj...>& target)
{
sigc::visit_each(action, target.functor_);
// Call sigc::visit_each(action, element) on each element in the
// target.obj_ tuple:
sigc::internal::tuple_for_each<internal::TupleVisitorVisitEach>(target.obj_, action);
}
};
#endif // DOXYGEN_SHOULD_SKIP_THIS
#ifndef SIGCXX_DISABLE_DEPRECATED
/** Creates an adaptor of type sigc::track_obj_functor which wraps a functor.
* @param func Functor that shall be wrapped.
* @param obj Trackable objects.
* @return Adaptor that executes func() on invocation.
*
* @newin{2,4}
* @deprecated Use sigc::track_object() instead.
*
* @ingroup track_obj
*/
template<typename T_functor, typename... T_obj>
inline decltype(auto)
track_obj(const T_functor& func, const T_obj&... obj)
{
return track_obj_functor<T_functor, T_obj...>(func, obj...);
}
#endif // SIGCXX_DISABLE_DEPRECATED
/** Creates an adaptor of type sigc::track_obj_functor which wraps a functor.
* @param func Functor that shall be wrapped.
* @param obj1 Trackable object, derived directly or indirectly from sigc::trackable.
* @param objs Zero or more trackable objects, derived directly or indirectly from sigc::trackable.
* @return Adaptor that executes func() on invocation.
*
* @newin{3,4}
*
* @ingroup track_obj
*/
template<typename T_functor, typename T_obj1, typename... T_objs>
inline decltype(auto)
track_object(const T_functor& func, const T_obj1& obj1, const T_objs&... objs)
{
static_assert(std::min<bool>({ std::is_base_of<sigc::trackable, T_obj1>::value,
std::is_base_of<sigc::trackable, T_objs>::value... }),
"Each trackable object must be derived from sigc::trackable.");
return track_obj_functor<T_functor, T_obj1, T_objs...>(func, obj1, objs...);
}
} /* namespace sigc */
#endif /* SIGC_ADAPTORS_TRACK_OBJ_H */
|