rcolyer.net
RC Lib  Version 202403231100
Caller.h
Go to the documentation of this file.
1 /////////////////////////////////////////////////////////////////////
2 //
3 // RC Library, (c) 2011-2014, Ryan A. Colyer
4 // Distributed under the Boost Software License, v1.0. (LICENSE.txt)
5 //
6 /// \file Caller.h
7 /// Provides a set of generalized functors for calling functions and
8 /// methods.
9 /////////////////////////////////////////////////////////////////////
10 
11 
12 #ifndef RC_CALLER_H
13 #define RC_CALLER_H
14 
15 #include "RCconfig.h"
16 
17 #ifdef CPP11
18 
19 #include "APtr.h"
20 #include "RevPtr.h"
21 #include <functional>
22 
23 namespace RC {
24  /// @cond PROTECTED
25 
26  template<class Ret=void, class... Params>
27  class Caller;
28 
29 
30  template<class Ret, class... Params>
31  class CallerBase {
32  public:
33  virtual ~CallerBase() { }
34  virtual CallerBase* Copy() const = 0;
35  virtual Ret operator()(Params... params) const = 0;
36  Caller<Ret, Params...> ToCaller() {
37  return Caller<Ret, Params...>(*this);
38  }
39  };
40  /// @endcond
41 
42 
43  /// The base class of Caller without return type or parameters specified.
44  /** For managed casting to the correct Caller type use DynCaller */
45  class UntypedCaller {
46  public:
47  virtual ~UntypedCaller() { }
48  };
49 
50 
51  /// @cond PROTECTED
52  template<class C, class Ret=void, class... Params>
53  class MemberCaller;
54 
55  template<class Functor, class Ret=void, class... Params>
56  class FunctorCaller;
57 
58  template<class Ret=void, class... Params>
59  class StaticCaller;
60  /// @endcond
61 
62 
63  /// A general purpose function class which can refer to any static method,
64  /// member method, functor, or lambda function.
65  /** Template parameters are specified as the return type followed by a list
66  * of the argument types.
67  * If access is attempted on an undefined Caller, ErrorMsgNull is thrown.
68  * If a member method Caller is constructed with the object as the first
69  * parameter, then the call is assigned to that object, which can be used
70  * for passing handlers.
71  * The convenience functions MakeCaller and MakeFunctor can be used
72  * for automatic type inference.
73  * Strict compile time type-checking is performed upon assignment or
74  * construction. To explicitly wrap with loose type-checking, use
75  * MakeFunctor on a Caller.
76  */
77  template<class Ret, class... Params>
78  class Caller : public UntypedCaller {
79  protected:
80  /// @cond PROTECTED
81  RC::APtr<CallerBase<Ret, Params...>> ptr;
82  /// @endcond
83  public:
84  /// Default constructor, refers to no function.
85  Caller() { }
86  /// Copy constructor.
87  Caller(const Caller& other) {
88  ptr = other.ptr;
89  }
90 
91  /// @cond PROTECTED
92  // This template exists to override Functor
93  template<class Ret2, class... Params2>
94  Caller(const Caller<Ret2, Params2...>& other) {
95  static_assert(std::is_same<Caller<Ret, Params...>,
97  "Attempted to copy-construct Callers with mismatched parameters");
98  ptr = other.ptr; // This should fail, giving compile error!
99  }
100  /// @endcond
101 
102  /// Construct a Caller to a member function of a specific object.
103  template<class C>
104  Caller(C* object, Ret (C::*func)(Params...)) {
105  *this = MemberCaller<C, Ret, Params...>(object, func);
106  }
107 
108  /// Construct a Caller to a member function of a specific object.
109  template<class C>
110  Caller(C& object, Ret (C::*func)(Params...)) {
111  *this = MemberCaller<C, Ret, Params...>(&object, func);
112  }
113 
114  /// Construct a Caller to a member function, where the inserted first
115  /// parameter is a reference to the object.
116  /** Usage example: class A { void F(int x) {} };
117  * Caller<void, A&, int> c(&A::F); c(5);
118  */
119  template<class C, class... OneFewerParams>
120  Caller(Ret (C::*func)(OneFewerParams...)) {
121  *this = Caller<Ret, C&, OneFewerParams...>(std::mem_fn(func));
122  }
123 
124  /// Construct a Caller to any general functor.
125  /** Note, for a Caller functor of a slightly different type, use
126  * MakeFunctor to avoid the intentional type-checking compile error.
127  */
128  template<class Functor>
129  Caller(Functor func) {
130  *this = FunctorCaller<Functor, Ret, Params...>(func);
131  }
132 
133  /// Destructor.
134  virtual ~Caller() { }
135 
136  /// @cond PROTECTED
137  Caller(const CallerBase<Ret, Params...>& caller_base) {
138  ptr = caller_base.Copy();
139  }
140 
141  Caller& operator=(const CallerBase<Ret, Params...>& caller_base) {
142  ptr = caller_base.Copy();
143  return *this;
144  }
145  /// @endcond
146 
147  /// Assign a Caller of identical type.
149  ptr = other.ptr;
150  return *this;
151  }
152 
153  /// Call the referenced function.
154  virtual Ret operator()(Params... params) const { return (*ptr)(params...); }
155 
156  /// True if a function was set.
157  bool IsSet() { return ptr.IsSet(); }
158 
159  /// Call the referenced function with the parameters given as RC::Tuple
160  /// tup.
161  template<class TupleType>
162  inline Ret Use(TupleType tup) { return tup.Apply(*this); }
163 
164  /// Return a functor with arguments bound using syntax identical to
165  /// std::bind.
166  /** The return type of this is an unspecified functor, but it can
167  * be wrapped in a MakeFunctor with the corresponding types.
168  */
169  template<class... Args>
170  auto Bind(Args... args) -> decltype(std::bind(*this, args...)) {
171  return std::bind(*this, args...);
172  }
173  };
174 
175 
176  /// @cond PROTECTED
177  template<class C, class Ret, class... Params>
178  class MemberCaller : public CallerBase<Ret, Params...> {
179  public:
180  MemberCaller(C* obj, Ret (C::*func)(Params...)) : obj(obj), func(func) { }
181  virtual Ret operator()(Params... params) const {
182  return (obj->*func)(params...);
183  }
184  virtual CallerBase<Ret, Params...>* Copy() const {
185  return new MemberCaller<C, Ret, Params...>(obj, func);
186  }
187 
188  protected:
189  C* obj;
190  Ret (C::*func)(Params...);
191  };
192 
193 
194  template<class Functor, class Ret, class... Params>
195  class FunctorCaller : public CallerBase<Ret, Params...> {
196  public:
197  FunctorCaller(Functor func) : func(func) { }
198 
199  virtual Ret operator()(Params... params) const { return func(params...); }
200  virtual CallerBase<Ret, Params...>* Copy() const {
201  return new FunctorCaller<Functor, Ret, Params...>(func);
202  }
203 
204  protected:
205  Functor func;
206  };
207 
208 
209  // This either obtains a StaticCaller, or generates errors during
210  // implicit casting of static function pointers to a FunctorCaller
211  // with parameters of an implicitly castable type.
212  template<class Ret, class... Params, class Ret2, class... Params2>
213  class FunctorCaller<Ret (*)(Params...), Ret2, Params2...>
214  : public StaticCaller<Ret2, Params2...> {
215  public:
216  FunctorCaller(Ret (*func)(Params...))
217  : StaticCaller<Ret2, Params2...>(func) { }
218  };
219 
220 
221  template<class Ret, class... Params>
222  class StaticCaller : public CallerBase<Ret, Params...> {
223  public:
224  StaticCaller(Ret (*func)(Params...)) : func(func) { }
225  virtual Ret operator()(Params... params) const {
226  return (*func)(params...);
227  }
228  virtual CallerBase<Ret, Params...>* Copy() const {
229  return new StaticCaller<Ret, Params...>(func);
230  }
231 
232  protected:
233  Ret (*func)(Params...);
234  };
235  /// @endcond
236 
237 
238  /// Generates a Caller for the member function of the given object, with
239  /// type inference.
240  template<class C, class Ret, class... Params>
241  Caller<Ret, Params...> MakeCaller(C* obj, Ret (C::*func)(Params...)) {
242  return MemberCaller<C, Ret, Params...>(obj, func);
243  }
244 
245  /// Generates a Caller for the member function of the given object, with
246  /// type inference.
247  template<class C, class Ret, class... Params>
248  Caller<Ret, Params...> MakeCaller(C& obj, Ret (C::*func)(Params...)) {
249  return MemberCaller<C, Ret, Params...>(&obj, func);
250  }
251 
252  /// Generates a Caller for the member function with type inference,
253  /// inserting a first parameter with a reference to the object.
254  template<class C, class Ret, class... Params>
255  Caller<Ret, C&, Params...> MakeCaller(Ret (C::*func)(Params...)) {
256  //return FunctorCaller<Ret (C::*)(Params...), Ret, C&, Params...>(std::mem_fn(func));
257  return Caller<Ret, C&, Params...>(std::mem_fn(func));
258  }
259 
260  /// Generates a Caller for the specified static function, with
261  /// type inference.
262  template<class Ret, class... Params>
263  Caller<Ret, Params...> MakeCaller(Ret (*func)(Params...)) {
264  return StaticCaller<Ret, Params...>(func);
265  }
266 
267 
268  /// A special generator for functors, which requires specifying the return
269  /// type and arguments.
270  /** Template parameters are specified as the return type followed by a list
271  * of the arguments.
272  */
273  template<class Ret, class... Params, class Functor>
274  Caller<Ret, Params...> MakeFunctor(Functor func) {
275  return FunctorCaller<Functor, Ret, Params...>(func);
276  }
277 
278 
279  /// Generates a Caller for the member function of the given object, with
280  /// type inference.
281  template<class C, class MemberFunc>
282  auto MakeCaller(Ptr<C> obj, MemberFunc func)
283  -> decltype(MakeCaller(obj.Raw(), func)) {
284 
285  return MakeCaller(obj.Raw(), func);
286  }
287 
288  /// Generates a Caller for the member function of the given object, with
289  /// type inference.
290  template<class C, class MemberFunc>
291  auto MakeCaller(APtr<C> obj, MemberFunc func)
292  -> decltype(MakeCaller(obj.Raw(), func)) {
293 
294  return MakeCaller(obj.Raw(), func);
295  }
296 
297  /// Generates a Caller for the member function of the given object, with
298  /// type inference.
299  template<class C, class MemberFunc>
300  auto MakeCaller(RevPtr<C> obj, MemberFunc func)
301  -> decltype(MakeCaller(obj.Raw(), func)) {
302 
303  return MakeCaller(obj.Raw(), func);
304  }
305 
306 
307  /// A typeless container for a Caller, which has methods for dynamically
308  /// casting it to the correct type.
309  class DynCaller {
310  protected:
311  /// @cond PROTECTED
312  APtr<UntypedCaller> caller;
313  /// @endcond
314  public:
315  /// Default constructor, contains no Caller.
317 
318  /// Construct a DynCaller which wraps new_caller.
319  template<class... Types>
321  : caller(new Caller<Types...>(new_caller)) {
322  }
323 
324  /// Creates a Caller referring to the given static function, and then
325  /// wraps it.
326  template<class Ret, class... Params>
327  DynCaller(Ret (*func)(Params...)) {
328  caller = new decltype(MakeCaller(func))(func);
329  }
330 
331 
332  /// Dynamically casts to the Caller of the specified template parameters,
333  /// or throws ErrorMsgCast if it fails.
334  template<class... Types>
335  inline Caller<Types...>& As() {
336  return caller.As<Caller<Types...>>();
337  }
338  /// Const version of As().
339  template<class... Types>
340  inline const Caller<Types...>& As() const {
341  return caller.As<Caller<Types...>>();
342  }
343 
344  /// True if this can cast to a Caller with the specified template
345  /// parameters.
346  template<class... Types>
347  inline bool CanCast() const {
348  return caller.CanCast<Caller<Types...>>();
349  }
350  };
351 }
352 
353 #endif // CPP11
354 
355 #endif // RC_CALLER_H
356 
357 
A reference counting ptr that is auto-deleted as the last copy leaves scope.
The version information and configuration settings for RC Lib.
A reference counting pointer that revokes (NULLs) all copies when one set to AutoRevoke(true) leaves ...
A reference counting ptr that auto-deletes what it points to when the last copy leaves scope or is ot...
Definition: APtr.h:39
A general purpose function class which can refer to any static method, member method,...
Definition: Caller.h:78
Caller(C *object, Ret(C::*func)(Params...))
Construct a Caller to a member function of a specific object.
Definition: Caller.h:104
Caller(C &object, Ret(C::*func)(Params...))
Construct a Caller to a member function of a specific object.
Definition: Caller.h:110
Caller()
Default constructor, refers to no function.
Definition: Caller.h:85
Caller(const Caller &other)
Copy constructor.
Definition: Caller.h:87
virtual Ret operator()(Params... params) const
Call the referenced function.
Definition: Caller.h:154
auto Bind(Args... args) -> decltype(std::bind(*this, args...))
Return a functor with arguments bound using syntax identical to std::bind.
Definition: Caller.h:170
Caller(Ret(C::*func)(OneFewerParams...))
Construct a Caller to a member function, where the inserted first parameter is a reference to the obj...
Definition: Caller.h:120
bool IsSet()
True if a function was set.
Definition: Caller.h:157
Caller(Functor func)
Construct a Caller to any general functor.
Definition: Caller.h:129
virtual ~Caller()
Destructor.
Definition: Caller.h:134
Ret Use(TupleType tup)
Call the referenced function with the parameters given as RC::Tuple tup.
Definition: Caller.h:162
Caller & operator=(const Caller< Ret, Params... > &other)
Assign a Caller of identical type.
Definition: Caller.h:148
A typeless container for a Caller, which has methods for dynamically casting it to the correct type.
Definition: Caller.h:309
DynCaller(Ret(*func)(Params...))
Creates a Caller referring to the given static function, and then wraps it.
Definition: Caller.h:327
bool CanCast() const
True if this can cast to a Caller with the specified template parameters.
Definition: Caller.h:347
Caller< Types... > & As()
Dynamically casts to the Caller of the specified template parameters, or throws ErrorMsgCast if it fa...
Definition: Caller.h:335
const Caller< Types... > & As() const
Const version of As().
Definition: Caller.h:340
DynCaller()
Default constructor, contains no Caller.
Definition: Caller.h:316
DynCaller(Caller< Types... > new_caller)
Construct a DynCaller which wraps new_caller.
Definition: Caller.h:320
A safe pointer class that throws an RC::ErrorMsgNull if a null dereference is attempted.
Definition: Ptr.h:31
A reference counting pointer that revokes (NULLs) all copies when one set to AutoRevoke(true) leaves ...
Definition: RevPtr.h:45
The base class of Caller without return type or parameters specified.
Definition: Caller.h:45
Definition: APtr.h:25
Caller< Ret, Params... > MakeFunctor(Functor func)
A special generator for functors, which requires specifying the return type and arguments.
Definition: Caller.h:274
Caller< Ret, Params... > MakeCaller(C *obj, Ret(C::*func)(Params...))
Generates a Caller for the member function of the given object, with type inference.
Definition: Caller.h:241
email address
— (c) 2015