Imported Upstream version 2.99.2
[platform/upstream/libsigc++.git] / sigc++ / functors / mem_fun.h
1 #ifndef _SIGC_FUNCTORS_MEM_FUN_H_
2 #define _SIGC_FUNCTORS_MEM_FUN_H_
3 #include <sigc++/type_traits.h>
4 #include <sigc++/limit_reference.h>
5 #include <sigc++/member_method_trait.h>
6
7 // implementation notes:
8 //  - we do not use bind here, because it would introduce
9 //    an extra copy and complicate the header include order if bind is
10 //    to have automatic conversion for member pointers.
11
12 namespace sigc {
13
14 /** @defgroup mem_fun mem_fun()
15  * mem_fun() is used to convert a pointer to a method to a functor.
16  *
17  * Optionally, a reference or pointer to an object can be bound to the functor.
18  *
19  * @note Only if the object type inherits from sigc::trackable, and the
20  * functor returned from mem_fun() is assigned to a sigc::slot, is the functor
21  * automatically cleared when the object goes out of scope!
22  *
23  * If the member function pointer is to an overloaded type, you must specify
24  * the types using template arguments starting with the first argument.
25  * It is not necessary to supply the return type.
26  *
27  * @par Example:
28  * @code
29  * struct foo : public sigc::trackable
30  * {
31  *   void bar(int) {}
32  * };
33  * foo my_foo;
34  * sigc::slot<void(int)> sl = sigc::mem_fun(my_foo, &foo::bar);
35  * // Note: f is not a slot. It will not be invalidated when my_foo is deleted.
36  * auto f = sigc::mem_fun(my_foo, &foo::bar); // Usually not what you want.
37  * @endcode
38  *
39  * For const methods mem_fun() takes a const reference or pointer to an object.
40  *
41  * @par Example:
42  * @code
43  * struct foo : public sigc::trackable
44  * {
45  *   void bar(int) const {}
46  * };
47  * const foo my_foo;
48  * sigc::slot<void(int)> sl = sigc::mem_fun(my_foo, &foo::bar);
49  * @endcode
50  *
51  * Use mem_fun#() if there is an ambiguity as to the number of arguments.
52  *
53  * @par Example:
54  * @code
55  * struct foo : public sigc::trackable
56  * {
57  *   void bar(int) {}
58  *   void bar(float) {}
59  *   void bar(int, int) {}
60  * };
61  * foo my_foo;
62  * sigc::slot<void(int)> sl = sigc::mem_fun1<int>(my_foo, &foo::bar);
63  * @endcode
64  *
65  * @ingroup sigcfunctors
66  */
67
68 template <class T_func, class... T_arg>
69 class mem_functor : public functor_base
70 {
71 public:
72   using object_type = typename internal::member_method_class<T_func>::type;
73
74   using function_type = T_func;
75   using result_type = typename internal::member_method_result<T_func>::type;
76
77   using obj_type_with_modifier = typename std::conditional_t<
78     internal::member_method_is_const<T_func>::value, const object_type, object_type>;
79
80   /// Constructs an invalid functor.
81   mem_functor() : func_ptr_(nullptr) {}
82
83   /** Constructs a mem_functor object that wraps the passed method.
84    * @param _A_func Pointer to method will be invoked from operator()().
85    */
86   explicit mem_functor(function_type _A_func) : func_ptr_(_A_func) {}
87
88   /** Execute the wrapped method operating on the passed instance.
89    * @param _A_obj Reference to instance the method should operate on.
90    * @param _A_a... Argument to be passed on to the method.
91    * @return The return value of the method invocation.
92    */
93   decltype(auto)
94   operator()(obj_type_with_modifier& _A_obj, type_trait_take_t<T_arg>... _A_a) const
95     { return (_A_obj.*func_ptr_)(_A_a...); }
96
97 protected:
98   function_type func_ptr_;
99 };
100
101
102 template <class T_func,
103   class... T_arg>
104 class bound_mem_functor
105 : mem_functor<T_func, T_arg...>
106 {
107   using base_type = mem_functor<T_func, T_arg...>;
108 public:
109   using function_type = typename base_type::function_type;
110   using result_type = typename base_type::result_type;
111
112   using object_type = typename base_type::object_type;
113
114   using obj_type_with_modifier = typename std::conditional_t<
115     internal::member_method_is_const<T_func>::value, const object_type, object_type>;
116   using T_limit_reference = typename std::conditional_t<
117     internal::member_method_is_const<T_func>::value,
118       limit_reference<const object_type>, limit_reference<object_type>>;
119
120   /** Constructs a bound_mem_functor object that wraps the passed method.
121    * @param _A_obj Reference to instance the method will operate on.
122    * @param _A_func Pointer to method will be invoked from operator()().
123    */
124   bound_mem_functor(obj_type_with_modifier& _A_obj, function_type _A_func)
125     : base_type(_A_func),
126       obj_(_A_obj)
127     {}
128
129   /** Execute the wrapped method operating on the stored instance.
130    * @param _A_a... Argument to be passed on to the method.
131    * @return The return value of the method invocation.
132    */
133   decltype(auto)
134   operator()(type_trait_take_t<T_arg>... _A_a) const
135     { return (obj_.invoke().*(this->func_ptr_))(_A_a...); }
136
137 //protected:
138   // Reference to stored object instance.
139   // This is the handler object, such as TheObject in void TheObject::signal_handler().
140   T_limit_reference obj_;
141 };
142
143
144 #ifndef DOXYGEN_SHOULD_SKIP_THIS
145 //template specialization of visitor<>::do_visit_each<>(action, functor):
146 /** Performs a functor on each of the targets of a functor.
147  * The function overload for sigc::bound_$1mem_functor performs a functor
148  * on the object instance stored in the sigc::bound_$1mem_functor object.
149  *
150  * @ingroup mem_fun
151  */
152 template <class T_func, class... T_arg>
153 struct visitor<bound_mem_functor<T_func, T_arg...> >
154 {
155   template <class T_action>
156   static void do_visit_each(const T_action& _A_action,
157                             const bound_mem_functor<T_func, T_arg...>& _A_target)
158   {
159     sigc::visit_each(_A_action, _A_target.obj_);
160   }
161 };
162 #endif // DOXYGEN_SHOULD_SKIP_THIS
163
164
165 /** Creates a functor of type sigc::mem_functor which wraps a  method.
166  * @param _A_func Pointer to method that should be wrapped.
167  * @return Functor that executes _A_func on invokation.
168  *
169  * @ingroup mem_fun
170  */
171 template <class T_return, class T_obj, class... T_arg>
172 inline decltype(auto)
173 mem_fun(T_return (T_obj::*_A_func)(T_arg...) )
174 { return mem_functor<
175     T_return (T_obj::*)(T_arg...) ,
176     T_arg...>(_A_func); }
177
178
179 /** Creates a functor of type sigc::const_mem_functor which wraps a const method.
180  * @param _A_func Pointer to method that should be wrapped.
181  * @return Functor that executes _A_func on invokation.
182  *
183  * @ingroup mem_fun
184  */
185 template <class T_return, class T_obj, class... T_arg>
186 inline decltype(auto)
187 mem_fun(T_return (T_obj::*_A_func)(T_arg...) const)
188 { return mem_functor<
189     T_return (T_obj::*)(T_arg...) const,
190     T_arg...>(_A_func); }
191
192
193 /** Creates a functor of type sigc::volatile_mem_functor which wraps a volatile method.
194  * @param _A_func Pointer to method that should be wrapped.
195  * @return Functor that executes _A_func on invokation.
196  *
197  * @ingroup mem_fun
198  */
199 template <class T_return, class T_obj, class... T_arg>
200 inline decltype(auto)
201 mem_fun(T_return (T_obj::*_A_func)(T_arg...) volatile)
202 { return mem_functor<
203     T_return (T_obj::*)(T_arg...) volatile,
204     T_arg...>(_A_func); }
205
206
207 /** Creates a functor of type sigc::const_volatile_mem_functor which wraps a const volatile method.
208  * @param _A_func Pointer to method that should be wrapped.
209  * @return Functor that executes _A_func on invokation.
210  *
211  * @ingroup mem_fun
212  */
213 template <class T_return, class T_obj, class... T_arg>
214 inline decltype(auto)
215 mem_fun(T_return (T_obj::*_A_func)(T_arg...) const volatile)
216 { return mem_functor<
217     T_return (T_obj::*)(T_arg...) const volatile,
218     T_arg...>(_A_func); }
219
220
221 /** Creates a functor of type sigc::bound_mem_functor which encapsulates a method and an object instance.
222  * @param _A_obj Reference to object instance the functor should operate on.
223  * @param _A_func Pointer to method that should be wrapped.
224  * @return Functor that executes @e _A_func on invokation.
225  *
226  * @ingroup mem_fun
227  */
228 template <class T_return, class T_obj, class T_obj2, class... T_arg>
229 inline decltype(auto)
230 mem_fun(/**/ T_obj& _A_obj, T_return (T_obj2::*_A_func)(T_arg...) )
231 {
232   return bound_mem_functor<
233     T_return (T_obj::*)(T_arg...) ,
234     T_arg...>(_A_obj, _A_func);
235 }
236
237 /** Creates a functor of type sigc::bound_const_mem_functor which encapsulates a method and an object instance.
238  * @param _A_obj Reference to object instance the functor should operate on.
239  * @param _A_func Pointer to method that should be wrapped.
240  * @return Functor that executes @e _A_func on invokation.
241  *
242  * @ingroup mem_fun
243  */
244 template <class T_return, class T_obj, class T_obj2, class... T_arg>
245 inline decltype(auto)
246 mem_fun(/*const*/ T_obj& _A_obj, T_return (T_obj2::*_A_func)(T_arg...) const)
247 {
248   return bound_mem_functor<
249     T_return (T_obj::*)(T_arg...) const,
250     T_arg...>(_A_obj, _A_func);
251 }
252
253
254 /** Creates a functor of type sigc::bound_volatile_mem_functor which encapsulates a method and an object instance.
255  * @param _A_obj Reference to object instance the functor should operate on.
256  * @param _A_func Pointer to method that should be wrapped.
257  * @return Functor that executes @e _A_func on invokation.
258  *
259  * @ingroup mem_fun
260  */
261 template <class T_return, class T_obj, class T_obj2, class... T_arg>
262 inline decltype(auto)
263 mem_fun(/**/ T_obj& _A_obj, T_return (T_obj2::*_A_func)(T_arg...) volatile)
264 {
265   return bound_mem_functor<
266     T_return (T_obj::*)(T_arg...) volatile,
267     T_arg...>(_A_obj, _A_func);
268 }
269
270
271 /** Creates a functor of type sigc::bound_const_volatile_mem_functor which encapsulates a method and an object instance.
272  * @param _A_obj Reference to object instance the functor should operate on.
273  * @param _A_func Pointer to method that should be wrapped.
274  * @return Functor that executes @e _A_func on invokation.
275  *
276  * @ingroup mem_fun
277  */
278 template <class T_return, class T_obj, class T_obj2, class... T_arg>
279 inline decltype(auto)
280 mem_fun(/*const*/ T_obj& _A_obj, T_return (T_obj2::*_A_func)(T_arg...) const volatile)
281 {
282   return bound_mem_functor<
283     T_return (T_obj::*)(T_arg...) const volatile,
284     T_arg...>(_A_obj, _A_func);
285 }
286
287
288
289 } /* namespace sigc */
290 #endif /* _SIGC_FUNCTORS_MEM_FUN_H_ */