AMSmartProperties  201
Core library
AMFunction.h
Go to the documentation of this file.
1 
11 #ifndef AMFUNCTION_H
12 #define AMFUNCTION_H
13 
14 #include <functional>
15 
16 namespace AMSmartProperties {
17 
18  #ifdef AMFUNCTION_DEFAULT_DATA_SIZE
19  static const int _AMFUNCTION_DEFAULT_DATA_SIZE = AMFUNCTION_DEFAULT_DATA_SIZE;
20  #else
21  static const int _AMFUNCTION_DEFAULT_DATA_SIZE = sizeof(void*);
22  #endif
23  /*
24  * Derives from @c unary_function or @c binary_function, or perhaps
25  * nothing, depending on the number of arguments provided. The
26  * primary template is the basis case, which derives nothing.
27  */
28  template<typename _Res, typename ... _ArgTypes>
29  struct _T_AMFN_maybe_unary_or_binary_function {
30  };
31 
32  // Derives from @c unary_function, as appropriate.
33  template<typename _Res, typename _T1>
34  struct _T_AMFN_maybe_unary_or_binary_function<_Res, _T1>
35  : std::unary_function<_T1, _Res> {
36  };
37 
38  // Derives from @c binary_function, as appropriate.
39  template<typename _Res, typename _T1, typename _T2>
40  struct _T_AMFN_maybe_unary_or_binary_function<_Res, _T1, _T2>
41  : std::binary_function<_T1, _T2, _Res> {
42  };
43 
44 
45  enum _E_AMFN_manager_operation {
46  _get_type_info,
47  _clone_functor,
48  _clone_functor_move,
49  _destroy_functor
50  };
51 
52  struct _T_AMFN_size_base {
53  static unsigned long _M_max;
54  };
55 
56 #ifdef COLLECTING_DATA
57 
58  template<typename _Functor>
59  struct _T_AMFN_size : _T_AMFN_size_base {
60 
61  unsigned long _M_get_size() {return _M_size;}
62 
63  static int _M_register_size() {
64  if (_M_max < sizeof(_Functor)) {
65  _M_max = sizeof(_Functor);
66  }
67  return sizeof(_Functor);
68  }
69  static unsigned long _M_size;
70  };
71  template<typename _Functor>
72  unsigned long _T_AMFN_size<_Functor>::_M_size = _T_AMFN_size<_Functor>::_M_register_size();
73 #endif
74 
75  /*
76  * Trait identifying "location-invariant" types, meaning that the
77  * address of the object (or any of its members) will not escape.
78  * Trivially copyable types are location-invariant and users can
79  * specialize this trait for other types.
80  */
81  template<typename _Tp>
82  struct _T_AMFN_is_location_invariant : std::is_trivially_copyable<_Tp>::type {
83  };
84 
85  template<typename _From, typename _To>
86  using _T_AMFN_check_func_return_type = std::__or_<std::is_void<_To>, std::is_same<_From, _To>/*, std::is_convertible<_From, _To>*/ >;
87 
88  union _T_AMFN_nocopy_types {
89  void *_M_object;
90  const void *_M_const_object;
91  char _M_data[_AMFUNCTION_DEFAULT_DATA_SIZE];
92  };
93 
94  template<typename _T, typename _U> constexpr size_t _T_AMFN_offset_of(_U _T::*member)
95  {
96  return (char*)&((_T*)nullptr->*member) - (char*)nullptr;
97  }
98 
99  class _T_AMFN_any_data {
100  public:
101  _T_AMFN_any_data() {}
102 
103  void *_M_access() { return &_M_data._M_data[0]; }
104 
105  const void *_M_access() const { return &_M_data._M_data[0]; }
106 
107  void *_M_access_ptr() { return _M_data._M_object; }
108 
109  const void *_M_access_ptr() const { return _M_data._M_object; }
110 
111  void _M_set_access_ptr(void *ptr) { _M_data._M_object = ptr; }
112 
113  template<typename _Tp>
114  _Tp &_M_get_functor_ptr() { return *static_cast<_Tp *>(_M_data._M_object); }
115 
116  template<typename _Tp>
117  const _Tp &_M_get_functor_ptr() const { return *static_cast<const _Tp *>(_M_data._M_object); }
118 
119  template<typename _Tp>
120  _Tp &_M_get_functor() { return *static_cast<_Tp *>(static_cast<void *>(&_M_data._M_data[0])); }
121 
122  template<typename _Tp>
123  const _Tp &
124  _M_get_functor() const { return *static_cast<const _Tp *>(static_cast<const void *>(&_M_data._M_data[0])); }
125 
126  _T_AMFN_nocopy_types _M_data;
127  };
128 
129  template<typename _Signature>
130  class _T_AMFN_kernel_base;
131 
132  template<typename _Signature>
133  class _T_AMFN_generic_functor;
134 
135  template<typename _Res, typename ... _ArgTypes>
136  class _T_AMFN_generic_functor<_Res(_ArgTypes...)> {
137  _Res operator ()(_ArgTypes ...);
138  };
139 
140  template<typename _Res, typename ... _ArgTypes>
141  class _T_AMFN_kernel_base<_Res(_ArgTypes...)> {
142  protected:
143  _T_AMFN_any_data _M_functor;
144 
145  typedef _Res (_T_AMFN_generic_functor<_Res(_ArgTypes...)>::*_T_AMFN_invoker_member_type)(_ArgTypes ...) const;
146 
147  void* _M_invoke_ptr;
148 
149  typedef const std::type_info *(*_T_AMFN_kernel_op_ptr)(_T_AMFN_kernel_base *_kernel_ptr, const _T_AMFN_any_data &_src,
150  _E_AMFN_manager_operation _op);
151 
152  _T_AMFN_kernel_op_ptr _M_kernel_op_ptr;
153 
154  public:
155  _T_AMFN_kernel_base(_T_AMFN_kernel_op_ptr _kernel_op_ptr) noexcept:
156  _M_functor(),
157  _M_invoke_ptr(nullptr),
158  _M_kernel_op_ptr(_kernel_op_ptr) {};
159 
160  _T_AMFN_kernel_base() noexcept:
161  _M_functor(),
162  _M_invoke_ptr(nullptr),
163  _M_kernel_op_ptr(nullptr) {};
164 
165  _T_AMFN_kernel_base(const _T_AMFN_kernel_base &_other) :
166  _M_functor(),
167  _M_invoke_ptr(_other._M_invoke_ptr),
168  _M_kernel_op_ptr(_other._M_kernel_op_ptr) {
169  if (_M_kernel_op_ptr) {
170  _M_kernel_op_ptr(this, _other._M_functor, _clone_functor);
171  }
172  }
173 
174  _T_AMFN_kernel_base(_T_AMFN_kernel_base &&_other) :
175  _M_functor(),
176  _M_invoke_ptr(_other._M_invoke_ptr),
177  _M_kernel_op_ptr(_other._M_kernel_op_ptr) {
178  if (_M_kernel_op_ptr) {
179  _M_kernel_op_ptr(this, _other._M_functor, _clone_functor_move);
180  }
181  _other._M_destroy();
182  }
183 
184  ~_T_AMFN_kernel_base() {
185  if (_M_kernel_op_ptr) {
186  _M_kernel_op_ptr(this, _M_functor, _destroy_functor);
187  }
188  }
189 
190  _T_AMFN_invoker_member_type _M_get_invoker() const
191  {
192  union {
193  _T_AMFN_invoker_member_type _M_invoker_member;
194  void* _M_void_ptr_array[2];
195  } u;
196  u._M_void_ptr_array[0] = _M_invoke_ptr;
197  u._M_void_ptr_array[1] = nullptr;
198  return u._M_invoker_member;
199  }
200 
201  _T_AMFN_kernel_base &operator=(const _T_AMFN_kernel_base &_other) {
202  if (_M_kernel_op_ptr) {
203  _M_kernel_op_ptr(this, _M_functor, _destroy_functor);
204  }
205  _M_invoke_ptr = _other._M_invoke_ptr;
206  _M_kernel_op_ptr = _other._M_kernel_op_ptr;
207  if (_M_kernel_op_ptr) {
208  _M_kernel_op_ptr(this, _other._M_functor, _clone_functor);
209  }
210  return *this;
211  }
212 
213  const _T_AMFN_any_data &_M_get_functor() const { return _M_functor; }
214 
215 
216  void _M_destroy() {
217  if (_M_kernel_op_ptr) {
218  _M_kernel_op_ptr(this, _M_functor, _destroy_functor);
219  }
220  _M_invoke_ptr = nullptr;
221  _M_kernel_op_ptr = nullptr;
222  }
223 
224  bool _M_empty() const noexcept {
225  return _M_invoke_ptr == nullptr;
226  }
227 
228 #if __cpp_rtti
229 
230  const std::type_info &_M_get_type_info() const noexcept {
231  if (_M_empty()) {
232  return typeid(void);
233  }
234  _T_AMFN_kernel_base *nonconstthis = const_cast<_T_AMFN_kernel_base *>(this);
235  return *_M_kernel_op_ptr(nonconstthis, _M_functor, _get_type_info);
236  }
237 
238 #endif
239  };
240 
241  template<typename _Signature, typename _Functor>
242  class _T_AMFN_kernel;
243 
244  template<typename _Signature, typename _Functor>
245  class _AMFunction_handler;
246 
247  template<typename _Res, typename _Functor, typename ... _ArgTypes>
248  class _T_AMFN_kernel<_Res(_ArgTypes ...), _Functor>
249  : public _T_AMFN_kernel_base<_Res(_ArgTypes...)> {
250 
251  static const std::size_t _M_max_size = sizeof(_T_AMFN_nocopy_types);
252  static const std::size_t _M_max_align = __alignof__(_T_AMFN_nocopy_types);
253  public:
254  static const bool _C_stored_locally =
255  (_T_AMFN_is_location_invariant<_Functor>::value
256  && (sizeof(_Functor) <= _M_max_size)
257  && (__alignof__(_Functor) <= _M_max_align)
258  && (_M_max_align % __alignof__(_Functor) == 0))
259  && (_AMFUNCTION_DEFAULT_DATA_SIZE > 0);
260  typedef std::integral_constant<bool, _C_stored_locally> _Local_storage;
261  typedef _T_AMFN_kernel_base<_Res(_ArgTypes...)> _T_Base;
262 
263  void _M_clone(const _T_AMFN_any_data &_functor, std::true_type) {
264  _Functor *vp = &_T_Base::_M_functor.template _M_get_functor<_Functor>();
265  ::new(vp) _Functor(_functor.template _M_get_functor<_Functor>());
266  }
267 
268  void _M_clone(const _T_AMFN_any_data &_functor, std::false_type) {
269  void *rv;
270  rv = static_cast<void *>(new _Functor(_functor.template _M_get_functor_ptr<_Functor>()));
271  _T_Base::_M_functor._M_set_access_ptr(rv);
272  }
273 
274  void _M_move(const _T_AMFN_any_data &_functor, std::true_type) {
275  _Functor *vp = &_T_Base::_M_functor.template _M_get_functor<_Functor>();
276  ::new(vp) _Functor(std::move(_functor.template _M_get_functor<_Functor>()));
277  }
278 
279  void _M_move(const _T_AMFN_any_data &_functor, std::false_type) {
280  void *rv;
281  rv = static_cast<void *>(new _Functor(std::move(_functor.template _M_get_functor_ptr<_Functor>())));
282  _T_Base::_M_functor._M_set_access_ptr(rv);
283  }
284 
285  void _M_init(const _Functor &_source, std::true_type) {
286  _Functor *vp = &_T_Base::_M_functor.template _M_get_functor<_Functor>();
287  ::new(vp) _Functor(_source);
288  }
289 
290  void _M_init(const _Functor &_source, std::false_type) {
291  void *rv;
292  rv = static_cast<void *>(new _Functor(_source));
293  _T_Base::_M_functor._M_set_access_ptr(rv);
294  }
295 
296  void _M_destroy(std::true_type) {
297  _T_Base::_M_functor.template _M_get_functor<_Functor>().~_Functor();
298  }
299 
300  void _M_destroy(std::false_type) {
301  delete &_T_Base::_M_functor.template _M_get_functor_ptr<_Functor>();
302  }
303 
304  static const std::type_info *
305  _M_manage_op(_T_AMFN_kernel_base<_Res(_ArgTypes ...)> *_me, const _T_AMFN_any_data &_functor,
306  _E_AMFN_manager_operation _op) {
307  switch (_op) {
308  case _destroy_functor:
309  static_cast<_T_AMFN_kernel *>(_me)->_M_destroy(_Local_storage());
310  break;
311  case _clone_functor:
312  static_cast<_T_AMFN_kernel *>(_me)->_M_clone(_functor, _Local_storage());
313  break;
314  case _clone_functor_move:
315  static_cast<_T_AMFN_kernel *>(_me)->_M_move(_functor, _Local_storage());
316  break;
317 #if __cpp_rtti
318  case _get_type_info:
319  return &typeid(_Functor);
320  break;
321 #endif
322  }
323  return nullptr;
324  }
325 
326  //typedef _Res (*_Invoker_type)(const void*, _ArgTypes ...);
327  typedef _Res (_AMFunction_handler<_Res(_ArgTypes...), _Functor>::*_T_AMFN_invoker_member_type)(_ArgTypes ...);
328  typedef _Res (_Functor::*_Invoker_functor_type)(_ArgTypes...) const;
329 
330  void _M_set_invoker(_Invoker_functor_type _invoker)
331  {
332  union {
333  _Invoker_functor_type _M_invoker_member;
334  void* _M_void_ptr_array[2];
335  } u;
336  u._M_invoker_member = _invoker;
337  if (u._M_void_ptr_array[1] != nullptr) {
338  throw std::bad_function_call();
339  }
340  _T_Base::_M_invoke_ptr = u._M_void_ptr_array[0];
341  }
342 
343  void _M_set_invoker_member(_T_AMFN_invoker_member_type _invoker)
344  {
345  union {
346  _T_AMFN_invoker_member_type _M_invoker_member;
347  void* _M_void_ptr_array[2];
348  } u;
349  u._M_invoker_member = _invoker;
350  if (u._M_void_ptr_array[1] != nullptr) {
351  throw std::bad_function_call();
352  }
353  _T_Base::_M_invoke_ptr = u._M_void_ptr_array[0];
354  }
355 
356  public:
357 
358  _T_AMFN_kernel(const _Functor &_functor, _T_AMFN_invoker_member_type invoke_ptr) :
359  _T_AMFN_kernel_base<_Res(_ArgTypes...)>(
360  &_M_manage_op
361  ) {
362  if (_C_stored_locally) {
363  _M_set_invoker(&_Functor::operator ());
364  }
365  else {
366  _M_set_invoker_member(invoke_ptr);
367  }
368  _M_init(_functor, _Local_storage());
369  };
370  };
371 
372 
373  template<typename _Res, typename _Functor, typename... _ArgTypes>
374  class _AMFunction_handler<_Res(_ArgTypes...), _Functor>
375  : public _T_AMFN_kernel<_Res(_ArgTypes...), _Functor> {
376  typedef _T_AMFN_kernel<_Res(_ArgTypes...), _Functor> _T_Base;
377 
378  public:
379  _AMFunction_handler(_Functor _functor) : _T_Base(_functor, &_AMFunction_handler<_Res(_ArgTypes...), _Functor>::_M_invoke) {}
380 
381  _Res _M_invoke(_ArgTypes ... __args) {
382  const void* newvfunctor = _T_Base::_M_get_functor()._M_access_ptr();
383  const _Functor& newfunctor = *static_cast<const _Functor*>(newvfunctor);
384  return newfunctor(std::forward<_ArgTypes>(__args)...);
385 
386  }
387  };
388 
389  template<typename _Functor, typename... _ArgTypes>
390  class _AMFunction_handler<void(_ArgTypes...), _Functor>
391  : public _T_AMFN_kernel<void(_ArgTypes...), _Functor> {
392  typedef _T_AMFN_kernel<void(_ArgTypes...), _Functor> _T_Base;
393 
394  public:
395  _AMFunction_handler(_Functor _functor) : _T_Base(_functor, &_AMFunction_handler<void(_ArgTypes...), _Functor>::_M_invoke) {}
396 
397  void _M_invoke(_ArgTypes ... __args) {
398  const void* newvfunctor = _T_Base::_M_get_functor()._M_access_ptr();
399  const _Functor& newfunctor = *static_cast<const _Functor*>(newvfunctor);
400  newfunctor(std::forward<_ArgTypes>(__args)...);
401  }
402  };
403 
404  template<typename _Signature>
405  class AMFunction;
406 
436  template<typename _Res, typename ... _ArgTypes>
437  class AMFunction<_Res(_ArgTypes ...)>
438  : public _T_AMFN_maybe_unary_or_binary_function<_Res, _ArgTypes ...> {
439 
440  _T_AMFN_kernel_base<_Res(_ArgTypes...)> _M_kernel;
441 
442  template<typename _Func,
443  typename _Res2 = typename std::result_of<_Func &(_ArgTypes ...)>::type>
444  struct _Callable : _T_AMFN_check_func_return_type<_Res2, _Res> {
445  };
446 
447  template<typename _Tp>
448  struct _Callable<AMFunction, _Tp> : std::false_type {
449  };
450 
451  template<typename _Cond, typename _Tp>
452  using _Requires = typename std::enable_if<_Cond::value, _Tp>::type;
453 
454 
455  public:
456 
461  AMFunction() noexcept: _M_kernel() {}
462 
467  AMFunction(std::nullptr_t) noexcept: _M_kernel() {}
468 
478  AMFunction(const AMFunction<_Res(_ArgTypes...)> &_other) : _M_kernel(_other._M_kernel) {}
479 
480 
490  AMFunction(AMFunction<_Res(_ArgTypes...)> &&_other) : _M_kernel(std::move(_other._M_kernel)) {}
491 
500  template<typename _Functor,
501  typename = _Requires<std::__not_<std::is_same<_Functor, AMFunction> >, void>,
502  typename = _Requires<_Callable<_Functor>, void> >
503  AMFunction(_Functor _f);
504 
505 
516  AMFunction &operator=(const AMFunction &_other) {
517  if (!_M_kernel._M_empty()) {
518  _M_kernel._M_destroy();
519  }
520  _M_kernel = _other._M_kernel;
521  return *this;
522  }
523 
534  AMFunction &operator=(AMFunction &&_other) {
535  if (!_M_kernel._M_empty()) {
536  _M_kernel._M_destroy();
537  }
538  _M_kernel = std::move(_other._M_kernel);
539  return *this;
540  }
541 
550  AMFunction &operator=(std::nullptr_t) {
551  if (!_M_kernel._M_empty()) {
552  _M_kernel._M_destroy();
553  }
554  return *this;
555  }
556 
567  template<typename _Functor>
568  _Requires<_Callable<typename std::decay<_Functor>::type>, AMFunction &>
569  operator=(_Functor &_f) {
570 #ifdef COLLECTING_DATA
571  static _T_AMFN_size<_Functor> _functor_size;
572  _functor_size._M_get_size();
573 #endif
574  if (!_M_kernel._M_empty()) {
575  _M_kernel._M_destroy();
576  }
577  typedef _AMFunction_handler<_Res(_ArgTypes...), _Functor> _My_handler;
578  ::new(&_M_kernel) _My_handler(_f);
579  return *this;
580  }
581 
590  explicit operator bool() const noexcept {
591  return !_M_kernel._M_empty();
592  }
593 
602  _Res operator()(_ArgTypes ... __args) const {
603  if (_M_kernel._M_empty()) {
604  throw std::bad_function_call();
605  }
606  const _T_AMFN_generic_functor<_Res(_ArgTypes...)>& obj = _M_kernel._M_get_functor().template _M_get_functor<_T_AMFN_generic_functor<_Res(_ArgTypes...)> >();
607  typedef _Res (_T_AMFN_generic_functor<_Res(_ArgTypes...)>::*_T_AMFN_invoker_member_type)(_ArgTypes ...) const;
608  _T_AMFN_invoker_member_type memberfn = _M_kernel._M_get_invoker();
609  _Res rv = ((obj).*(memberfn))(std::forward<_ArgTypes>(__args)...);
610  return rv;
611  }
612 
613 #if __cpp_rtti
614 
622  const std::type_info &target_type() const noexcept {
623  const std::type_info &_typeinfo_result = _M_kernel._M_get_type_info();
624  return _typeinfo_result;
625  }
626 
627 #endif
628 
643  static unsigned long getMaximumFunctorSize() noexcept {
644 
645  unsigned long _return_value = -1;
646 #ifdef COLLECTING_DATA
647  _return_value = _T_AMFN_size_base::_M_max;
648 #endif
649  return _return_value;
650  }
651  };
652 
653  template<typename _Res, typename ... _ArgTypes>
654  template<typename _Functor, typename, typename>
655  AMFunction<_Res(_ArgTypes...)>::AMFunction(_Functor __f) {
656 #ifdef COLLECTING_DATA
657  static _T_AMFN_size<_Functor> _functor_size;
658  _functor_size._M_get_size();
659 #endif
660  typedef _AMFunction_handler<_Res(_ArgTypes...), _Functor> _My_handler;
661  ::new(&_M_kernel) _My_handler(__f);
662  };
663 
672  template<typename _Res, typename ... _Args>
673  inline bool
674  operator==(const AMFunction<_Res(_Args ...)> &__f, std::nullptr_t) noexcept {
675  return !static_cast<bool>(__f);
676  }
677 
686  template<typename _Res, typename ... _Args>
687  inline bool
688  operator==(std::nullptr_t, const AMFunction<_Res(_Args ...)> &__f) noexcept {
689  return !static_cast<bool>(__f);
690  }
691 
699  template<typename _Res, typename ... _Args>
700  inline bool
701  operator!=(const AMFunction<_Res(_Args ...)> &__f, std::nullptr_t) noexcept {
702  return static_cast<bool>(__f);
703  }
704 
712  template<typename _Res, typename ... _Args>
713  inline bool
714  operator!=(std::nullptr_t, const AMFunction<_Res(_Args ...)> &__f) noexcept {
715  return static_cast<bool>(__f);
716  }
717 
718 }//namespace AMSmartProperties
720 #endif //AMFUNCTION_H
AMFunction & operator=(const AMFunction &_other)
AMFunction assignment operator.
Definition: AMFunction.h:516
AMFunction & operator=(std::nullptr_t)
AMFunction assignment to zero.
Definition: AMFunction.h:550
Definition: AMProperty.h:32
AMFunction & operator=(AMFunction &&_other)
AMFunction move-assignment operator.
Definition: AMFunction.h:534
_Requires< _Callable< typename std::decay< _Functor >::type >, AMFunction & > operator=(_Functor &_f)
AMFunction assignment to a new target.
Definition: AMFunction.h:569
bool operator!=(std::nullptr_t, const AMFunction< _Res(_Args ...)> &__f) noexcept
Compares an AMFunction target with nullptr.
Definition: AMFunction.h:714
_Res operator()(_ArgTypes ... __args) const
Invokes the AMFunction targeted by *this.
Definition: AMFunction.h:602
static unsigned long getMaximumFunctorSize() noexcept
Determines maximum functor size used in program.
Definition: AMFunction.h:643
AMFunction() noexcept
Default construct creates an empty AMFunction.
Definition: AMFunction.h:461
Definition: AMFunction.h:16
bool operator==(std::nullptr_t, const AMFunction< _Res(_Args ...)> &__f) noexcept
Compares an AMFunction target with nullptr.
Definition: AMFunction.h:688
AMFunction(std::nullptr_t) noexcept
Creates an empty AMFunction.
Definition: AMFunction.h:467
AMFunction(AMFunction< _Res(_ArgTypes...)> &&_other)
AMFunction move constructor.
Definition: AMFunction.h:490
AMFunction(const AMFunction< _Res(_ArgTypes...)> &_other)
AMFunction copy constructor.
Definition: AMFunction.h:478