Autowiring  1.0.3
A C++ Inversion of Control Framework
auto_arg.h
Go to the documentation of this file.
1 // Copyright (C) 2012-2015 Leap Motion, Inc. All rights reserved.
2 #pragma once
3 #include "auto_id.h"
4 
5 class AutoPacket;
6 class CoreContext;
7 
8 namespace autowiring {
9 
10 template <class T> class auto_in;
11 
12 /*
13  The auto_arg<T> classes are used to generate of auto_in and auto_out types
14  based on the argument T.
15  The core functionality is that all argument types are treated as standard
16  types, and can be re-derived from those standard types.
17  It is expected that every parent of auto_arg will define:
18  - id_type (an unqualified T)
19  - base_type (a T qualified by const and/or &)
20  - shared_type (the pointer T from which the parent inherits)
21  Furthermore, by classifying arguments in terms of orientation and fundamental
22  T, auto_arg enables the specification of a principal T to any class
23  implementing an AutoFilter method.
24  */
25 
29 template<class T>
30 class auto_arg
31 {
32 public:
33  typedef const T& type;
34  typedef type arg_type;
35  typedef auto_id_t<T> id_type;
36  static const bool is_input = true;
37  static const bool is_output = false;
38  static const bool is_rvalue = false;
39  static const bool is_shared = false;
40  static const bool is_multi = false;
41  static const int tshift = 0;
42 
43  template<class C>
44  static const T& arg(C& packet) {
45  (void) auto_id_t_init<T, true>::init;
46  return packet.template Get<T>();
47  }
48 };
49 
53 template<class T>
54 class auto_arg<const T>:
55  public auto_arg<T>
56 {};
57 
61 template<class T>
62 class auto_arg<const T&>
63 {
64 public:
65  typedef const T& type;
66  typedef type arg_type;
67  typedef auto_id_t<T> id_type;
68  static const bool is_input = true;
69  static const bool is_output = false;
70  static const bool is_rvalue = false;
71  static const bool is_shared = false;
72  static const bool is_multi = false;
73  static const int tshift = 0;
74 
75  template<class C>
76  static const T& arg(C& packet) {
77  (void)auto_id_t_init<T, false>::init;
78  return packet.template Get<T>();
79  }
80 };
81 
85 template<class T>
86 class auto_arg<T&&>
87 {
88 public:
89  typedef T&& type;
90  typedef type arg_type;
91  typedef auto_id_t<T> id_type;
92  static const bool is_input = true;
93  static const bool is_output = true;
94  static const bool is_rvalue = true;
95  static const bool is_shared = false;
96  static const bool is_multi = false;
97  static const int tshift = 0;
98 
99  template<class C>
100  static T&& arg(C& packet) {
101  (void) auto_id_t_init<T, false>::init;
102  return packet.template GetRvalue<T>();
103  }
104 
105  template<class C>
106  static void Commit(C& packet, T& val) {
107  // Do nothing. Modify val in place, no need to commit
108  }
109 };
110 
114 template<class T>
115 class auto_arg<std::shared_ptr<const T>>
116 {
117 public:
118  typedef const std::shared_ptr<const T>& type;
119  typedef type arg_type;
120  typedef auto_id_t<T> id_type;
121  static const bool is_input = true;
122  static const bool is_output = false;
123  static const bool is_rvalue = false;
124  static const bool is_shared = true;
125  static const bool is_multi = false;
126  static const int tshift = 0;
127 
128  template<class C>
129  static const std::shared_ptr<const T>& arg(C& packet) {
130  (void) auto_id_t_init<T, false>::init;
131 
132  static const std::shared_ptr<const T> null;
133  auto retVal = packet.template GetShared<T>();
134  if (!retVal)
135  return null;
136  return *retVal;
137  }
138 };
139 
143 template<class T>
144 class auto_arg<const std::shared_ptr<const T>&>:
145  public auto_arg<std::shared_ptr<const T>>
146 {};
147 
151 template<class T>
152 class auto_arg<std::shared_ptr<T>&&>
153 {
154 public:
155  typedef std::shared_ptr<T>&& type;
156  typedef type arg_type;
157  typedef auto_id_t<T> id_type;
158  static const bool is_input = true;
159  static const bool is_output = true;
160  static const bool is_rvalue = true;
161  static const bool is_shared = true;
162  static const bool is_multi = false;
163  static const int tshift = 0;
164 
165  template<class C>
166  static std::shared_ptr<T>&& arg(C& packet) {
167  (void) auto_id_t_init<T, false>::init;
168  return packet.template GetRvalueShared<T>();
169  }
170 
171  template<class C>
172  static void Commit(C& packet, std::shared_ptr<T> val) {
173  if (!val)
174  packet.template RemoveDecoration<T>();
175  }
176 };
177 
181 template<class T>
182 class auto_arg<T*>
183 {
184 public:
185  static_assert(std::is_const<T>::value, "Pointer-typed input parameters must point to a const-qualified type (T must be const-qualified)");
186  typedef T* type;
187  typedef T* arg_type;
188  typedef auto_id_t<T*> id_type;
189  static const bool is_input = true;
190  static const bool is_output = false;
191  static const bool is_rvalue = false;
192  static const bool is_shared = false;
193  static const bool is_multi = false;
194  static const int tshift = 0;
195 
196  template<class C>
197  static const T* arg(C& packet) {
198  (void) auto_id_t_init<T, false>::init;
199  return packet.template Get<const T*>();
200  }
201 };
202 
203 namespace detail {
204 
212 template<class T, bool has_default = std::is_constructible<T>::value, bool has_autofilter = std::is_constructible<T, AutoPacket&>::value>
214 
215 template<class T, bool has_default>
216 struct auto_arg_ctor_helper<T, has_default, true> {
217  static std::shared_ptr<T> arg(AutoPacket& packet) {
218  return std::make_shared<T>(packet);
219  }
220 };
221 
222 template<class T, bool has_default>
223 struct auto_arg_ctor_helper<T, has_default, false> {
224  static_assert(has_default, "Cannot speculatively construct an output argument of type T, it doesn't have any available constructors");
225 
226  template<void* (*)(size_t)>
227  struct fn {};
228 
229  template<typename U>
230  static std::shared_ptr<U> Allocate(fn<&U::operator new>*) {
231  return std::shared_ptr<U>(new U);
232  }
233 
234  template<typename U>
235  static std::shared_ptr<U> Allocate(...) {
236  return std::make_shared<U>();
237  }
238 
239  static std::shared_ptr<T> arg(AutoPacket&) {
240  // Use make shared, if we can; if static new is present on this type, though, then we have to use
241  // the uglier two-part construction syntax
242  return Allocate<T>(nullptr);
243  }
244 };
245 
246 } // end of namespace detail
247 
251 template<class T>
252 class auto_arg<T&>
253 {
254 public:
255  typedef std::shared_ptr<T> type;
256 
257  // Utility type, required to dereference the std::shared_ptr
258  struct arg_type {
259  arg_type(std::shared_ptr<T>& arg) :
260  arg(*arg)
261  {}
262 
263  T& arg;
264  operator T&() const { return arg; }
265  };
266 
267  typedef auto_id_t<T> id_type;
268  static const bool is_input = false;
269  static const bool is_output = true;
270  static const bool is_rvalue = false;
271  static const bool is_shared = false;
272  static const bool is_multi = false;
273  static const int tshift = 0;
274 
275  static std::shared_ptr<T> arg(AutoPacket& packet) {
276  // Need to ensure the identifier is initialized properly, we can do a full
277  // initialization because this is a byref output type
278  (void) auto_id_t_init<T>::init;
280  }
281 
282  template<class C>
283  static void Commit(C& packet, type val) {
284  packet.template Decorate<T>(val);
285  }
286 };
287 
291 template<class T>
292 class auto_arg<std::shared_ptr<T>&>:
293  public auto_arg<T&>
294 {
295 public:
296  static const bool is_shared = true;
297 
298  // Utility type, required to dereference the std::shared_ptr
299  struct arg_type {
300  arg_type(std::shared_ptr<T>& arg) :
301  arg(arg)
302  {}
303 
304  std::shared_ptr<T>& arg;
305  operator std::shared_ptr<T>&() const { return arg; }
306  };
307 
308  template<class C>
309  static std::shared_ptr<T> arg(C&) {
310  (void) auto_id_t_init<T, false>::init;
311  return std::shared_ptr<T>();
312  }
313 };
314 
318 template<class T>
319 class auto_arg<std::shared_ptr<T>> {
320  static_assert(
321  std::is_same<T, AutoPacket>::value,
322  "std::shared_ptr<AutoPacket> is the only T that may be supplied as a non-const shared input"
323  );
324 };
325 
329 template<>
331 {
332 public:
333  typedef CoreContext& type;
334  typedef CoreContext& arg_type;
335  typedef auto_id_t<CoreContext> id_type;
336  static const bool is_input = false;
337  static const bool is_output = false;
338  static const bool is_rvalue = false;
339  static const bool is_shared = false;
340  static const bool is_multi = false;
341  static const int tshift = 0;
342 
343  static CoreContext& arg(AutoPacket&);
344 };
345 
349 template<>
350 class auto_arg<std::shared_ptr<CoreContext>>
351 {
352 public:
353  typedef std::shared_ptr<CoreContext> type;
354  typedef std::shared_ptr<CoreContext> arg_type;
355  typedef auto_id_t<CoreContext> id_type;
356  static const bool is_input = false;
357  static const bool is_output = false;
358  static const bool is_rvalue = false;
359  static const bool is_shared = false;
360  static const bool is_multi = false;
361  static const int tshift = 0;
362 
363  static std::shared_ptr<CoreContext> arg(AutoPacket&);
364 };
365 
372 template<class T>
373 class auto_arg<T const **>
374 {
375 public:
376  typedef const T** arg_type;
377  struct type {
378  type(type&& rhs) :
379  ptr(std::move(rhs.ptr))
380  {}
381 
382  explicit type(std::unique_ptr<const T*[]> ptr) :
383  ptr{std::move(ptr)}
384  {}
385 
386  std::unique_ptr<const T*[]> ptr;
387 
388  operator const T**(void) const { return ptr.get(); }
389  };
390 
391  typedef auto_id_t<T> id_type;
392  static const bool is_input = true;
393  static const bool is_output = false;
394  static const bool is_rvalue = false;
395  static const bool is_shared = false;
396  static const bool is_multi = true;
397  static const int tshift = 0;
398 
399  template<class C>
400  static type arg(C& packet) {
401  (void) auto_id_t_init<T, false>::init;
402  return type{packet.template GetAll<T>()};
403  }
404 };
405 
406 template<class T>
407 class auto_arg<T const *const*>:
408  public auto_arg<T const**>
409 {};
410 
414 template<class T>
415 class auto_arg<std::shared_ptr<const T>*>
416 {
417 public:
418  typedef std::shared_ptr<const T>* arg_type;
419 
420  struct type {
421  type(type&& rhs) :
422  ptr(std::move(rhs.ptr))
423  {}
424 
425  explicit type(std::unique_ptr<std::shared_ptr<const T>[]> ptr) :
426  ptr{std::move(ptr)}
427  {}
428 
429  std::unique_ptr<std::shared_ptr<const T>[]> ptr;
430 
431  operator std::shared_ptr<const T>*(void) const { return ptr.get(); }
432  };
433 
434  typedef auto_id_t<T> id_type;
435  static const bool is_input = true;
436  static const bool is_output = false;
437  static const bool is_rvalue = false;
438  static const bool is_shared = false;
439  static const bool is_multi = true;
440  static const int tshift = 0;
441 
442  template<class C>
443  static type arg(C& packet) {
444  (void) auto_id_t_init<T, false>::init;
445  return type{packet.template GetAllShared<T>()};
446  }
447 };
448 
449 
450 template<class T>
451 class auto_arg<const std::shared_ptr<const T>*>:
452  public auto_arg<std::shared_ptr<const T>*>
453 {};
454 
458 template<class T>
459 struct arg_is_out {
460  static const bool value = auto_arg<T>::is_output;
461 };
462 
463 }
STL namespace.
A decorator-style processing packet
Definition: AutoPacket.h:49
Reinterpret copied argument as input
Definition: auto_arg.h:30
Fundamental type of required input arguments of AutoFilter methods.
Definition: auto_arg.h:10
Multi-in specialization
Definition: auto_arg.h:373
A top-level container class representing an autowiring domain, a minimum broadcast domain...
Definition: CoreContext.h:106
Definition: auto_arg.h:8
Construction helper for output-by-reference decoration types
Definition: auto_arg.h:213
Utility predicate, used to assess whether T is an output argument
Definition: auto_arg.h:459