CsSignal  1.3.1
cs_internal.h
1 /***********************************************************************
2 *
3 * Copyright (c) 2016-2024 Barbara Geller
4 * Copyright (c) 2016-2024 Ansel Sermersheim
5 *
6 * This file is part of CsSignal.
7 *
8 * CsSignal is free software, released under the BSD 2-Clause license.
9 * For license details refer to LICENSE provided with this project.
10 *
11 * CsSignal is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 *
15 * https://opensource.org/licenses/BSD-2-Clause
16 *
17 ***********************************************************************/
18 
19 #ifndef LIB_CS_INTERNAL_H
20 #define LIB_CS_INTERNAL_H
21 
22 #include <functional>
23 #include <memory>
24 #include <tuple>
25 
26 #if ! defined (CS_DOXYPRESS)
27 
28 namespace CsSignal {
29 
30 class SlotBase;
31 
32 namespace Internal {
33 
34 // 1
35 template<class T, class U, class = void>
36 class cs_check_connect_args
37  : public cs_check_connect_args<T, decltype(&U::operator())>
38 {
39 };
40 
41 
42 // 2 slot is a func ptr, first signal and first slot parameters match
43 template<class T, class ...ArgsX, class ...ArgsY>
44 class cs_check_connect_args<void (*)(T, ArgsX...), void (*)(T, ArgsY...)>
45  : public cs_check_connect_args<void (*) (ArgsX...), void (*) (ArgsY...)>
46 {
47 };
48 
49 // slot is a func ptr, slot has no parameters
50 template<class ...ArgsX>
51 class cs_check_connect_args<void (*)(ArgsX...), void (*)()>
52  : public std::integral_constant<bool, true>
53 {
54 };
55 
56 // slot is a func ptr, signal has the same number of parms as the slot, types mismatch
57 template<class ...ArgsX, class ...ArgsY>
58 class cs_check_connect_args < void (*)(ArgsX...), void (*)(ArgsY...),
59  typename std::enable_if< sizeof...(ArgsX) == sizeof...(ArgsY) &&
60  ! std::is_same<std::tuple<ArgsX...>, std::tuple<ArgsY...>>::value >::type>
61  : public std::integral_constant<bool, false>
62 {
63 };
64 
65 // slot is a func ptr, signal has fewer number of parms than the slot
66 template<class ...ArgsX, class ...ArgsY>
67 class cs_check_connect_args < void (*)(ArgsX...), void (*)(ArgsY...),
68  typename std::enable_if<sizeof...(ArgsX) < sizeof...(ArgsY)>::type >
69  : public std::integral_constant<bool, false>
70 {
71 };
72 
73 
74 // 3 slot is a method ptr
75 template<class T, class...ArgsX, class...ArgsY>
76 class cs_check_connect_args<void (*)(ArgsX...), void (T::*)(ArgsY...) >
77  : public cs_check_connect_args<void (*)(ArgsX...), void (*) (ArgsY...)>
78 {
79 };
80 
81 // slot is a const method ptr
82 template<class T, class...ArgsX, class...ArgsY>
83 class cs_check_connect_args<void (*)(ArgsX...), void (T::*)(ArgsY...) const>
84  : public cs_check_connect_args<void (*)(ArgsX...), void (*) (ArgsY...)>
85 {
86 };
87 
88 
89 // compile time tests
90 template<class Sender, class SignalClass>
91 void cs_testConnect_SenderSignal()
92 {
93  static_assert( std::is_base_of<SignalClass, Sender>::value,
94  "Signal is not defined in the sender class");
95 }
96 
97 template<class Slot_LambdaType, class ...SignalArgs>
98 void cs_testConnect_SignalSlotArgs_1()
99 {
100  static_assert( cs_check_connect_args<void (*)(SignalArgs...), Slot_LambdaType>::value,
101  "Incompatible signal/slot arguments");
102 }
103 
104 template<class SlotClass, class Receiver>
105 void cs_testConnect_ReceiverSlot()
106 {
107  static_assert( std::is_base_of<SlotClass, Receiver>::value,
108  "Slot is not defined in the receiver class");
109 }
110 
111 template<class Signal_ArgType, class Slot_ArgType>
112 void cs_testConnect_SignalSlotArgs_2()
113 {
114  static_assert( cs_check_connect_args<Signal_ArgType, Slot_ArgType>::value,
115  "Incompatible signal/slot arguments");
116 }
117 
118 // marker for a function which returns a void
119 class CSVoidReturn
120 {
121 };
122 
123 
124 // ** unpack_function (1)
125 // ** index_sequence unpacks a tuple into arguments for function pointer
126 
127 template<typename ...FunctionArgTypes, typename FunctionReturn, typename ...TupleTypes, size_t ...Ks>
128 FunctionReturn cs_unpack_function_args_internal(FunctionReturn (*functionPtr)(FunctionArgTypes...),
129  const std::tuple<TupleTypes...> &data, std::index_sequence<Ks...>)
130 {
131  return functionPtr(std::get<Ks>(data)...);
132 }
133 
134 // (api) specialization function pointer
135 template<typename ...FunctionArgTypes, typename FunctionReturn, typename ...TupleTypes>
136 FunctionReturn cs_unpack_function_args(FunctionReturn (*functionPtr)(FunctionArgTypes...),
137  const std::tuple<TupleTypes...> &data)
138 {
139  return cs_unpack_function_args_internal(functionPtr, data, std::index_sequence_for<TupleTypes...> {} );
140 }
141 
142 // (api) specialization function pointer, return type is void
143 template<typename ...FunctionArgTypes, typename ...TupleTypes>
144 CSVoidReturn cs_unpack_function_args(void (*functionPtr)(FunctionArgTypes...), const std::tuple<TupleTypes...> &data)
145 {
146  cs_unpack_function_args_internal(functionPtr, data, std::index_sequence_for<TupleTypes...> {} );
147  return CSVoidReturn {};
148 }
149 
150 
151 // ** unpack_function (2)
152 // ** index_sequence unpacks a tuple into arguments for a method pointer
153 
154 template<typename MethodClass, class MethodReturn, typename ...MethodArgTypes, typename ...TupleTypes, size_t ...Ks>
155 MethodReturn cs_unpack_method_args_internal(MethodClass *obj, MethodReturn (MethodClass::*methodPtr)(MethodArgTypes...),
156  const std::tuple<TupleTypes...> &data, std::index_sequence<Ks...>)
157 {
158  return (obj->*methodPtr)(std::get<Ks>(data)...);
159 }
160 
161 // (api) specialization method pointer
162 template<typename MethodClass, class MethodReturn, typename ...MethodArgTypes, typename ...TupleTypes>
163 MethodReturn cs_unpack_method_args(MethodClass *obj, MethodReturn (MethodClass::*methodPtr)(MethodArgTypes...),
164  const std::tuple<TupleTypes...> &data)
165 {
166  return cs_unpack_method_args_internal(obj, methodPtr, data, std::index_sequence_for<TupleTypes...> {} );
167 }
168 
169 // (api) specialization for method pointer, return type is void
170 template<typename MethodClass, typename ...MethodArgTypes, typename ...TupleTypes>
171 CSVoidReturn cs_unpack_method_args(MethodClass *obj, void (MethodClass::*methodPtr)(MethodArgTypes...),
172  const std::tuple<TupleTypes...> &data)
173 {
174  cs_unpack_method_args_internal(obj, methodPtr, data, std::index_sequence_for<TupleTypes...> {} );
175  return CSVoidReturn {};
176 }
177 
178 // ** index_sequence unpacks a tuple into arguments for a const method pointer
179 
180 template<typename MethodClass, class MethodReturn, typename ...MethodArgTypes, typename ...TupleTypes, size_t ...Ks>
181 MethodReturn cs_unpack_method_args_internal(const MethodClass *obj,
182  MethodReturn (MethodClass::*methodPtr)(MethodArgTypes...) const,
183  const std::tuple<TupleTypes...> &data, std::index_sequence<Ks...>)
184 {
185  return (obj->*methodPtr)(std::get<Ks>(data)...);
186 }
187 
188 // (api) specialization for const method pointer
189 template<typename MethodClass, class MethodReturn, typename ...MethodArgTypes, typename ...TupleTypes>
190 MethodReturn cs_unpack_method_args(const MethodClass *obj,
191  MethodReturn (MethodClass::*methodPtr)(MethodArgTypes...) const,
192  const std::tuple<TupleTypes...> &data)
193 {
194  return cs_unpack_method_args_internal(obj, methodPtr, data, std::index_sequence_for<TupleTypes...> {} );
195 }
196 
197 // (api) specialization for const method pointer, return type is void
198 template<typename MethodClass, typename ...MethodArgTypes, typename ...TupleTypes>
199 CSVoidReturn cs_unpack_method_args(const MethodClass *obj, void (MethodClass::*methodPtr)(MethodArgTypes...) const,
200  const std::tuple<TupleTypes...> &data)
201 {
202  cs_unpack_method_args_internal(obj, methodPtr, data, std::index_sequence_for<TupleTypes...> {} );
203  return CSVoidReturn {};
204 }
205 
206 
207 // ** templated classes used to add or remove types to a tuple
208 
209 template <class T1, class T2>
210 class prePend
211 {
212  // required class to utilize a specialization
213 };
214 
215 template <class T, class ...Ts>
216 class prePend<T, std::tuple<Ts...>>
217 {
218  public:
219  using type = typename std::tuple<T, Ts...>;
220 };
221 
222 template <class T1>
223 class strip
224 {
225  public:
226  // contains nothing
227  using type = typename std::tuple<>;
228 };
229 
230 template <class T1, class T2, class ...Ts>
231 class strip<std::tuple<T1, T2, Ts...>>
232 {
233  public:
234  using type = typename prePend<T1, typename strip<std::tuple<T2, Ts...> >::type>::type;
235 };
236 
237 
238 // ** templated classes for generating a data type from a parameter pack
239 
240 template<unsigned int ...Vs>
241 class intValues
242 {
243 };
244 
245 template<unsigned int Max, unsigned int ...Vs>
246 class makeIntValues : public makeIntValues <Max - 1, Max - 1, Vs...>
247 {
248 };
249 
250 template<unsigned int ...Vs>
251 class makeIntValues<0, Vs...> : public intValues<Vs...>
252 {
253 };
254 
255 // ** templated class to remove the last data type from the "tuple data type"
256 
257 template <class ...Ts>
258 class removeLastType
259 {
260  public:
261  using type = typename strip< std::tuple<Ts...> >::type;
262 };
263 
264 
265 
266 // ** templated functions, to strip the last data element from a tuple
267 
268 template<unsigned int ...Vs, class ...Ts>
269 typename removeLastType<Ts...>::type internalRemoveData(intValues<Vs...>, std::tuple<Ts...> tupleValue)
270 {
271  (void) tupleValue;
272  return std::forward_as_tuple(std::get<Vs>(tupleValue)...);
273 }
274 
275 template<class ...Ts>
276 typename removeLastType<Ts...>::type funcRemoveData(std::tuple<Ts...> tupleValue)
277 {
278  return internalRemoveData(makeIntValues<sizeof...(Ts) - 1>(), tupleValue);
279 }
280 
281 
282 // ** class used to store slot data in a tuple
283 
284 class TeaCupAbstract
285 {
286  public:
287  virtual ~TeaCupAbstract() {}
288 };
289 
290 // 1
291 template<class ...Ts>
292 class TeaCup : public TeaCup< typename removeLastType<Ts...>::type>
293 {
294  public:
295  template<class T>
296  explicit TeaCup(T lambda);
297 
298  std::tuple<Ts...> getData() const;
299 
300  private:
301  std::function<std::tuple<Ts...> ()> m_lambda;
302 };
303 
304 template<class ...Ts>
305 template<class T>
306 TeaCup<Ts...>::TeaCup(T lambda)
307  : TeaCup< typename removeLastType<Ts...>::type >( [this]() { return funcRemoveData(m_lambda()); } ),
308  m_lambda(std::move(lambda))
309 {
310 }
311 
312 template<class ...Ts>
313 std::tuple<Ts...> TeaCup<Ts...>::getData() const
314 {
315  return m_lambda();
316 }
317 
318 // 2 specialization for no args
319 template<>
320 class TeaCup<>: public TeaCupAbstract
321 {
322  public:
323  template<class T>
324  explicit TeaCup(T lambda);
325 
326  std::tuple<> getData() const;
327 };
328 
329 template<class T>
330 TeaCup<>::TeaCup(T)
331 {
332 }
333 
334 inline std::tuple<> TeaCup<>::getData() const
335 {
336  // empty tuple
337  return std::tuple<> {};
338 }
339 
340 // 3 specialization, tuple with args
341 template<class ...Ts>
342 class TeaCup< std::tuple<Ts...> >: public TeaCup<Ts...>
343 {
344  public:
345  template<class T>
346  explicit TeaCup(T lambda);
347 };
348 
349 template<class ...Ts>
350 template<class T>
351 TeaCup<std::tuple<Ts...>>::TeaCup(T lambda)
352  : TeaCup<Ts...>(std::move(lambda))
353 {
354 }
355 
356 
357 // ** template functions use Index_Sequence to convert a tuple to R
358 
359 template<class R, class T, size_t ...Ks>
360 R convert_tuple_internal(T &data, std::index_sequence<Ks...>)
361 {
362  return R {std::get<Ks>(data)...};
363 }
364 
365 template<class R, class ...Ts>
366 R convert_tuple(std::tuple<Ts...> &data)
367 {
368  return convert_tuple_internal<R> (data, std::index_sequence_for<Ts...> {} );
369 }
370 
371 
372 // ** templated class, used to store data for signals
373 
374 template<class ...Ts>
375 class TeaCup_Data: public TeaCup<Ts...>
376 {
377  public:
378  TeaCup_Data(bool needs_copying, Ts...);
379  std::tuple<Ts...> getData() const;
380 
381  private:
382  std::shared_ptr< std::tuple<typename std::remove_reference<Ts>::type...> > m_copyOfData;
383  std::tuple<Ts...> m_data;
384 };
385 
386 template<class ...Ts>
387 TeaCup_Data<Ts...>::TeaCup_Data(bool needs_copying, Ts...Vs)
388  : TeaCup<Ts...>( [this]() { return m_data; } ),
389  m_copyOfData(needs_copying ? new std::tuple<typename std::remove_reference<Ts>::type...> (Vs...) : nullptr),
390  m_data(needs_copying ? convert_tuple<std::tuple<Ts...>> (*m_copyOfData) : std::tuple<Ts...> (Vs...) )
391 {
392 }
393 
394 template<class ...Ts>
395 std::tuple<Ts...> TeaCup_Data<Ts...>::getData() const
396 {
397  return m_data;
398 }
399 
400 
401 // ** class to store method pointer for signals and slots
402 
403 class BentoAbstract
404 {
405  public:
406  virtual ~BentoAbstract() {}
407 
408  virtual bool operator ==(const BentoAbstract &right) const = 0;
409  bool operator !=(const BentoAbstract &right) const;
410 
411  virtual void invoke(SlotBase *receiver, const TeaCupAbstract *dataPack) const = 0;
412  virtual std::unique_ptr<BentoAbstract> clone() const = 0;
413 };
414 
415 inline bool BentoAbstract::operator !=(const BentoAbstract &right) const
416 {
417  return ! (*this == right);
418 }
419 
420 template<class T>
421 class Bento : public virtual BentoAbstract
422 {
423  public:
424  Bento(T ptr);
425 
426  bool operator ==(const BentoAbstract &right) const override;
427 
428  void invoke(SlotBase *receiver, const TeaCupAbstract *dataPack) const override;
429  std::unique_ptr<BentoAbstract> clone() const override;
430 
431  template<class MethodReturn, class ...MethodArgs>
432  void invoke_internal(const TeaCupAbstract *dataPack, MethodReturn (T::*methodPtr)(MethodArgs...) const) const;
433 
434  template<class MethodReturn, class ...MethodArgs>
435  void invoke_internal(const TeaCupAbstract *dataPack, MethodReturn (T::*methodPtr)(MethodArgs...)) const;
436 
437  T m_lambda;
438 };
439 
440 template<class FunctionReturn, class ...FunctionArgs>
441 class Bento<FunctionReturn (*)(FunctionArgs...)> : public virtual BentoAbstract
442 {
443  public:
444  Bento(FunctionReturn (*ptr)(FunctionArgs...));
445 
446  bool operator ==(const BentoAbstract &right) const override;
447 
448  std::unique_ptr<BentoAbstract> clone() const override;
449  void invoke(SlotBase *receiver, const TeaCupAbstract *dataPack) const override;
450 
451  FunctionReturn (*m_methodPtr)(FunctionArgs...);
452 };
453 
454 template<class MethodClass, class MethodReturn, class...MethodArgs>
455 class Bento<MethodReturn(MethodClass::*)(MethodArgs...)>: public virtual BentoAbstract
456 {
457  public:
458  Bento(MethodReturn(MethodClass::*ptr)(MethodArgs...) );
459 
460  bool operator ==(const BentoAbstract &right) const override ;
461  void invoke(SlotBase *receiver, const TeaCupAbstract *dataPack) const override;
462  std::unique_ptr<BentoAbstract> clone() const override;
463 
464  MethodReturn(MethodClass::*m_methodPtr)(MethodArgs...);
465 };
466 
467 // specialization, const method pointer
468 template<class MethodClass, class MethodReturn, class...MethodArgs>
469 class Bento<MethodReturn(MethodClass::*)(MethodArgs...) const>: public virtual BentoAbstract
470 {
471  public:
472  Bento(MethodReturn(MethodClass::*ptr)(MethodArgs...) const);
473 
474  bool operator ==(const BentoAbstract &right) const override;
475 
476  void invoke(SlotBase *receiver, const TeaCupAbstract *dataPack) const override;
477  std::unique_ptr<BentoAbstract> clone() const override;
478 
479  MethodReturn(MethodClass::*m_methodPtr)(MethodArgs...) const;
480 };
481 
482 
483 // (1) lambda
484 template<class T>
485 Bento<T>::Bento(T lambda)
486  : m_lambda(lambda)
487 {
488 }
489 
490 template<class T>
491 std::unique_ptr<BentoAbstract> Bento<T>::clone() const
492 {
493  return std::make_unique<Bento<T>>(*this);
494 }
495 
496 template<class T>
497 bool Bento<T>::operator ==(const BentoAbstract &) const
498 {
499  // can not compare two lambdas
500  return false;
501 }
502 
503 template<class T>
504 void Bento<T>::invoke(SlotBase *, const TeaCupAbstract *dataPack) const
505 {
506  // T must be a class or it will be a compiler error
507  auto methodPtr = &T::operator();
508 
509  this->invoke_internal(dataPack, methodPtr);
510 }
511 
512 template<class T>
513 template<class MethodReturn, class ...MethodArgs>
514 void Bento<T>::invoke_internal(const TeaCupAbstract *dataPack, MethodReturn (T::*methodPtr)(MethodArgs...) const) const
515 {
516  // handles non-mutable, captured variables are const
517 
518  // dynamic cast will return a valid ptr if the slot has equal or less parameters
519  // retrieve ptr to teaCup object, which contains the data
520  const TeaCup<MethodArgs...> *teaCup = dynamic_cast<const TeaCup<MethodArgs...> *>(dataPack);
521 
522  if (teaCup) {
523  // expand arguments
524  std::tuple<MethodArgs...> &&args = teaCup->getData();
525 
526  // unpack the tuple, then call the methodPtr
527  cs_unpack_method_args(&m_lambda, methodPtr, args);
528  }
529 }
530 
531 template<class T>
532 template<class MethodReturn, class ...MethodArgs>
533 void Bento<T>::invoke_internal(const TeaCupAbstract *dataPack, MethodReturn (T::*methodPtr)(MethodArgs...)) const
534 {
535  // handles mutable, captured variables are non-const
536 
537  // dynamic cast will return a valid ptr if the slot has equal or less parameters
538  // retrieve ptr to teaCup object, which contains the data
539  const TeaCup<MethodArgs...> *teaCup = dynamic_cast<const TeaCup<MethodArgs...> *>(dataPack);
540 
541  if (teaCup) {
542  // expand arguments
543  std::tuple<MethodArgs...> &&args = teaCup->getData();
544 
545  auto object = const_cast<typename std::remove_const<T>::type *>(&m_lambda);
546 
547  // unpack the tuple, then call the methodPtr
548  cs_unpack_method_args(object, methodPtr, args);
549  }
550 }
551 
552 // (2) specialization, function pointer
553 template<class FunctionReturn, class ...FunctionArgs>
554 Bento<FunctionReturn (*)(FunctionArgs...)>::Bento(FunctionReturn (*ptr)(FunctionArgs...)) :
555  m_methodPtr(ptr)
556 {
557 }
558 
559 template<class FunctionReturn, class ...FunctionArgs>
560 std::unique_ptr<BentoAbstract> Bento<FunctionReturn (*)(FunctionArgs...)>::clone() const
561 {
562  return std::make_unique<Bento<FunctionReturn (*)(FunctionArgs...)>>(*this);
563 }
564 
565 template<class FunctionReturn, class ...FunctionArgs>
566 bool Bento<FunctionReturn (*)(FunctionArgs...)>::operator ==(const BentoAbstract &right) const
567 {
568  bool retval = false;
569 
570  const Bento<FunctionReturn (*)(FunctionArgs...)> *temp;
571  temp = dynamic_cast<const Bento <FunctionReturn (*)(FunctionArgs...)> *> (&right);
572 
573  if (temp) {
574  retval = (this->m_methodPtr == temp->m_methodPtr);
575  }
576 
577  return retval;
578 }
579 
580 template<class FunctionReturn, class ...FunctionArgs>
581 void Bento<FunctionReturn (*)(FunctionArgs...)>::invoke(SlotBase *, const TeaCupAbstract *dataPack) const
582 {
583  // no need to verify receiver (slotBase *) since it is not used
584 
585  // dynamic cast will return a valid ptr if the slot has equal or less parameters
586  // retrieve ptr to teaCup object, which contains the data
587  const TeaCup<FunctionArgs...> *teaCup = dynamic_cast<const TeaCup<FunctionArgs...> *>(dataPack);
588 
589  if (teaCup) {
590  // expand arguments
591  std::tuple<FunctionArgs...> &&args = teaCup->getData();
592 
593  // unpack the tuple, then call the methodPtr
594  cs_unpack_function_args(m_methodPtr, args);
595  }
596 }
597 
598 
599 // (3) specialization, method pointer
600 template<class MethodClass, class MethodReturn, class...MethodArgs>
601 Bento<MethodReturn(MethodClass::*)(MethodArgs...)>::Bento(MethodReturn(MethodClass::*ptr)(MethodArgs...))
602  : m_methodPtr(ptr)
603 {
604 }
605 
606 template<class MethodClass, class MethodReturn, class...MethodArgs>
607 std::unique_ptr<BentoAbstract> Bento<MethodReturn(MethodClass::*)(MethodArgs...)>::clone() const
608 {
609  return std::make_unique<Bento<MethodReturn(MethodClass::*)(MethodArgs...)>>(*this);
610 }
611 
612 template<class MethodClass, class MethodReturn, class...MethodArgs>
613 bool Bento<MethodReturn(MethodClass::*)(MethodArgs...)>::operator ==(const BentoAbstract &right) const
614 {
615  bool retval = false;
616 
617  const Bento<MethodReturn(MethodClass::*)(MethodArgs...)> *temp;
618  temp = dynamic_cast<const Bento <MethodReturn(MethodClass::*)(MethodArgs...)> *> (&right);
619 
620  if (temp) {
621  retval = (this->m_methodPtr == temp->m_methodPtr);
622  }
623 
624  return retval;
625 }
626 
627 template<class MethodClass, class MethodReturn, class ...MethodArgs>
628 void Bento<MethodReturn(MethodClass::*)(MethodArgs...)>::invoke(SlotBase *receiver, const TeaCupAbstract *dataPack) const
629 {
630  if (! receiver) {
631  return;
632  }
633 
634  MethodClass *t_receiver = dynamic_cast<MethodClass *>(receiver);
635 
636  if (t_receiver) {
637  // dynamic cast will return a valid ptr if the slot has equal or less parameters
638  // retrieve ptr to teaCup object, which contains the data
639  const TeaCup<MethodArgs...> *teaCup = dynamic_cast<const TeaCup<MethodArgs...> *>(dataPack);
640 
641  if (teaCup) {
642  // expand arguments
643  std::tuple<MethodArgs...> &&args = teaCup->getData();
644 
645  // unpacks the tuple, then calls the methodPtr
646  cs_unpack_method_args(t_receiver, m_methodPtr, args);
647  }
648  }
649 }
650 
651 
652 // (4) specialization, pointer to const method
653 template<class MethodClass, class MethodReturn, class...MethodArgs>
654 Bento<MethodReturn(MethodClass::*)(MethodArgs...) const>::Bento(MethodReturn(MethodClass::*ptr)(MethodArgs...) const)
655  : m_methodPtr(ptr)
656 {
657 }
658 
659 template<class MethodClass, class MethodReturn, class...MethodArgs>
660 std::unique_ptr<BentoAbstract> Bento<MethodReturn(MethodClass::*)(MethodArgs...) const>::clone() const
661 {
662  return std::make_unique<Bento<MethodReturn(MethodClass::*)(MethodArgs...) const>>(*this);
663 }
664 
665 template<class MethodClass, class MethodReturn, class...MethodArgs>
666 bool Bento<MethodReturn(MethodClass::*)(MethodArgs...) const>::operator ==(const BentoAbstract &right) const
667 {
668  bool retval = false;
669 
670  const Bento<MethodReturn(MethodClass::*)(MethodArgs...) const> *temp;
671  temp = dynamic_cast<const Bento <MethodReturn(MethodClass::*)(MethodArgs...) const> *> (&right);
672 
673  if (temp) {
674  retval = (this->m_methodPtr == temp->m_methodPtr);
675  }
676 
677  return retval;
678 }
679 
680 template<class MethodClass, class MethodReturn, class ...MethodArgs>
681 void Bento<MethodReturn(MethodClass::*)(MethodArgs...) const>::invoke(SlotBase *receiver, const TeaCupAbstract *dataPack) const
682 {
683  if (! receiver) {
684  return;
685  }
686 
687  MethodClass *t_receiver = dynamic_cast<MethodClass *>(receiver);
688 
689  if (t_receiver) {
690  // dynamic cast will return a valid ptr if the slot has equal or less parameters
691 
692  // retrieve ptr to teaCup object, which contains the data
693  const TeaCup<MethodArgs...> *teaCup = dynamic_cast<const TeaCup<MethodArgs...> *>(dataPack);
694 
695  if (teaCup) {
696  // expand arguments
697  std::tuple<MethodArgs...> &&args = teaCup->getData();
698 
699  // unpacks the tuple, then calls the methodPtr
700  cs_unpack_method_args(t_receiver, m_methodPtr, args);
701  }
702  }
703 }
704 
705 } }
706 
707 #endif // doxypress
708 
709 #endif