libqi-api  2.8.7.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
anyfunctionfactory.hxx
Go to the documentation of this file.
1 #pragma once
2 /*
3 ** Copyright (C) 2013 Aldebaran Robotics
4 ** See COPYING for the license
5 */
6 
7 #ifndef _QITYPE_DETAIL_ANYFUNCTIONFACTORY_HXX_
8 #define _QITYPE_DETAIL_ANYFUNCTIONFACTORY_HXX_
9 
10 #include <boost/mpl/for_each.hpp>
11 #include <boost/mpl/transform_view.hpp>
12 #include <boost/mpl/find_if.hpp>
13 #include <boost/mpl/vector.hpp>
14 #include <boost/mpl/pop_front.hpp>
15 #include <boost/mpl/at.hpp>
16 #include <boost/mpl/placeholders.hpp>
17 #include <boost/mpl/max_element.hpp>
18 #include <boost/mpl/transform.hpp>
19 #include <boost/type_traits/remove_reference.hpp>
20 #include <boost/type_traits/add_pointer.hpp>
21 #include <boost/type_traits/remove_const.hpp>
22 #include <boost/type_traits/remove_pointer.hpp>
23 #include <boost/type_traits/is_member_function_pointer.hpp>
24 #include <boost/function_types/function_type.hpp>
25 #include <boost/function_types/function_arity.hpp>
26 #include <boost/function_types/function_pointer.hpp>
27 #include <boost/function_types/member_function_pointer.hpp>
28 #include <boost/function_types/result_type.hpp>
29 #include <boost/function_types/parameter_types.hpp>
30 #include <boost/bind.hpp>
31 #include <boost/any.hpp>
32 #include <boost/thread/mutex.hpp>
33 #include <qi/atomic.hpp>
34 #include <qi/anyvalue.hpp>
35 #include <ka/typetraits.hpp>
36 
37 namespace qi
38 {
39  namespace detail
40  {
41  /* General idea: code generated to make a function call taking a
42  * void*, long, or long& is the same.
43  * So we reduce the function types for which we effectively implement
44  * call, and bounce the equivalent functions to it.
45  */
46 
47  /* ASSERTS
48  * We make some asumptions for this code to work. Failure on any of
49  * those asumptions will *not* be detected and will cause undefined behavior.
50  * - typesystem Storage for pointer types is by-value, and by-pointer for everything else
51  * - compiler-generated code is the same when calling a function:
52  * - with argument T and EqType<T>::type
53  * - with return type T and EqType<T>::rType
54  * - with all pointer types and all reference types for argument/return type
55  */
56 
57  class Class{}; // dummy class placeholder
58 
59  /* For each type, get equivalent type, and if it is a reference
60  * Equivalent type is a type for which when types are substituted in a
61  * function call, compiler-generated code is the same.
62  * *WARNING* some magic occurs for return type, so have a separate rule
63  * which matches less stuffs for it.
64  */
65  template <typename T, bool isWordSize>
66  struct EqTypeBase
67  {
68  using type = T;
69  using rType = T;
70  using isReference = typename boost::is_reference<T>::type;
71  static const int dbgTag = 0;
72  };
73 
74  template<typename T>
75  struct EqTypeBase<T, true>
76  {
77  using type = typename boost::mpl::if_<typename boost::is_fundamental<T>::type, void*, T>::type;
78  using rType = typename boost::mpl::if_<typename boost::is_fundamental<T>::type, void*, T>::type;
79  using isReference = typename boost::is_reference<T>::type;
80  static const int dbgTag = 1;
81  };
82 
83  template <typename T>
84  struct EqType: public EqTypeBase<T, sizeof(T) == sizeof(void*)>
85  {
86  };
87 
88  template <> struct EqType<void>
89  {
90  using type = void;
91  using rType = void*;
92  using isReference = boost::false_type;
93  };
94 
95  template<> struct EqType<double>
96  {
97  using type = double;
98  using rType = double;
99  using isReference = boost::false_type;
100  };
101 
102  template<> struct EqType<float>
103  {
104  using type = float;
105  using rType = float;
106  using isReference = boost::false_type;
107  };
108 
109  template<> struct EqType<bool>
110  {
111  using type = bool;
112  using rType = bool;
113  using isReference = boost::false_type;
114  };
115 
116  template <typename T> struct EqType<T&>
117  {
118  using type = void*;
119  using rType = void*;
120  using isReference = boost::true_type;
121  static const int dbgTag = 2;
122  };
123 
124  template <typename T> struct EqType<T const &>
125  {
126  using type = void*;
127  using rType = void*;
128  using isReference = boost::true_type;
129  static const int dbgTag = 3;
130  };
131 
132  // HACK: mark pointer as references, because typesystem transmit them
133  // by-value
134  template <typename T>
135  struct EqType<T *>
136  {
137  using type = void*;
138  using rType = void*;
139  using isReference = boost::true_type;
140  static const int dbgTag = 4;
141  };
142 
143  // helper to compute a reference mask iterating through a mpl sequence
144  template<typename S, typename I, int p>
145  struct RefMasqBuilderHelper
146  {
147  using type = typename boost::mpl::deref<I>::type;
148  static const unsigned int isRef = EqType<type>::isReference::value;
149  static const unsigned long vSelf = isRef << p;
150  static const unsigned long val = vSelf + RefMasqBuilderHelper<S,
151  typename boost::mpl::next<I>::type, p+1>::val;
152  };
153 
154  template<typename S, int p>
155  struct RefMasqBuilderHelper<S, typename boost::mpl::end<S>::type, p>
156  {
157  static const unsigned long val = 0;
158  };
159 
160  /* Equivalent function info for function type F
161  *
162  */
163  template<typename F> struct EqFunctionBare
164  {
165  using Components = typename boost::function_types::components<F>::type;
166 
167  using Arguments = typename boost::function_types::parameter_types<F>::type;
168  using Result = typename boost::function_types::result_type<F>::type;
169 
170  // need to handle result type separately
171  using EqArguments = typename boost::mpl::transform<Arguments, EqType<boost::mpl::_1>>::type;
172  using EqResult = typename EqType<Result>::rType;
173  using EqComponents = typename boost::mpl::push_front<EqArguments, EqResult>::type;
174 
175  // Bit b is set if argument index b+1 (0=return type) is a reference.
176  static const unsigned long refMask = RefMasqBuilderHelper<Components,
177  typename boost::mpl::begin<Components>::type, 0>::val;
178  using type = typename boost::function_types::function_type<EqComponents>::type;
179  };
180 
181  template<typename F> struct EqMemberFunction
182  {
183  using Components = typename boost::function_types::components<F>::type;
184  // we need to handle object type and return type separately
185  // arguments with object
186  using MethodArguments = typename boost::function_types::parameter_types<F>::type;
187  // arguments without object
188  using Arguments = typename boost::mpl::pop_front<MethodArguments>::type;
189  // return type
190  using Result = typename boost::function_types::result_type<F>::type;
191  using EqArguments = typename boost::mpl::transform<Arguments, EqType<boost::mpl::_1> >::type;
192  using EqResult = typename EqType<Result>::rType;
193  // push equivalent object type
194  using EqComponentsInt = typename boost::mpl::push_front<EqArguments, detail::Class&>::type;
195  using EqComponents = typename boost::mpl::push_front<EqComponentsInt, EqResult>::type;
196  using type = typename boost::function_types::member_function_pointer<EqComponents>::type;
197  static const unsigned long refMask = RefMasqBuilderHelper<Components,
198  typename boost::mpl::begin<Components>::type, 0>::val;
199  };
200 
201  template<typename F>
202  struct EqFunction:
203  public boost::mpl::if_<typename boost::is_member_function_pointer<F>::type,
204  EqMemberFunction<F>,
205  EqFunctionBare<F> >::type
206  {};
207  /* args[i] is a pointer to an element of expected type DROPPING ref
208  * we will make the call by dereferencing all args, so we must add
209  * one layer of pointer to effective refs
210  *
211  */
212  inline void transformRef(void** args, void** out, unsigned int sz, unsigned long refMask)
213  {
214  for (unsigned i=0; i<sz; ++i)
215  {
216  if (refMask & (1 << (i+1))) // bit 0 is for return type
217  out[i] = &args[i];
218  else
219  out[i] = args[i];
220  }
221  }
222 
234  {
235  public:
236  AnyReferenceCopy &operator()() { return *this; }
237  };
238 
239  template <typename T>
241  {
242  template<class X>
243  static void assignAnyRef(AnyReference* ref, X&& any)
244  {
245  using CopyType = typename std::decay<T>::type;
246  *ref = AnyReference(qi::typeOf<T>(), new CopyType(std::forward<X>(any)));
247  }
248  };
249 
250  template <typename T>
251  struct AssignAnyRef<T*>
252  {
253  static void assignAnyRef(AnyReference* ref, T* any)
254  {
255  *ref = AnyReference::from(any);
256  }
257  };
258 
259  template <typename T>
260  void operator,(AnyReferenceCopy& g, T&& any)
261  {
262  AssignAnyRef<T>::assignAnyRef(&g, std::forward<T>(any));
263  }
264 
265  // makeCall function family
266  // accepts a bare function, boost function, member function
267  // we handled byval/byref in refMask/transformRef, so bypass
268  // entirely ptrFromStorage.
269 
270 #define callArg(z, n, _) \
271  BOOST_PP_COMMA_IF(n) * (typename boost::remove_reference<P##n>::type*)args[n]
272 #define makeCall(n, argstypedecl, argstype, argsdecl, argsues, comma) \
273  template <typename R comma argstypedecl> \
274  void* makeCall(R (*f)(argstype), void** args) \
275  { \
276  detail::AnyReferenceCopy val; \
277  val(), f(BOOST_PP_REPEAT(n, callArg, _)); \
278  return val.rawValue(); \
279  }
281 #undef makeCall
282 
283 #ifdef _WIN32
284 #define STATIC_IF_SAFE
285 #else
286 #define STATIC_IF_SAFE static
287 #endif
288 
289 // hacks are disabled for boost::function (refMask forced to 0)
290 // so use ptrFromStorage.
291 #define declType(z, n, _) \
292  STATIC_IF_SAFE TypeInterface* type_##n = \
293  typeOf<typename boost::remove_reference<P##n>::type>();
294 #define callArgBF(z, n, _) \
295  BOOST_PP_COMMA_IF(n) * (typename boost::remove_reference<P##n>::type*) \
296  type_##n->ptrFromStorage(&args[n])
297 
298 #define makeCall(n, argstypedecl, argstype, argsdecl, argsues, comma) \
299  template <typename R comma argstypedecl> \
300  void* makeCall(boost::function<R(argstype)> f, void** args) \
301  { \
302  BOOST_PP_REPEAT(n, declType, _) detail::AnyReferenceCopy val; \
303  val(), f(BOOST_PP_REPEAT(n, callArgBF, _)); \
304  return val.rawValue(); \
305  }
307 #undef makeCall
308 
309 #define makeCall(n, argstypedecl, argstype, argsdecl, argsues, comma) \
310  template <typename R comma argstypedecl> \
311  void* makeCall(R (Class::*f)(argstype), void* instance, void** args) \
312  { \
313  detail::AnyReferenceCopy val; \
314  Class* cptr = *(Class**)instance; \
315  val(), ((*cptr).*f)(BOOST_PP_REPEAT(n, callArg, _)); \
316  return val.rawValue(); \
317  }
319 #undef makeCall
320 
321 #define makeCall_(n, argstypedecl, argstype, argsdecl, argsues, comma) \
322  template <typename R comma argstypedecl> \
323  void* makeCall(R (Class::*f)(argstype), void** args) \
324  { \
325  return makeCall(f, args[0], args + 1); \
326  }
327 
329 #undef callArg
330 #undef makeCall_
331 
332 #ifdef QITYPE_TRACK_FUNCTIONTYPE_INSTANCES
333  // debug-tool to monitor function type usage
334  void QI_API functionTypeTrack(const std::string& functionName);
335  void QI_API functionTypeDump();
336 #endif
337  }
338 
339  struct InfosKeyMask: public std::vector<TypeInterface*>
340  {
341  public:
342  InfosKeyMask(const std::vector<TypeInterface*>& b, unsigned long mask)
343  : std::vector<TypeInterface*>(b), _mask(mask) {}
344  bool operator < (const InfosKeyMask& b) const
345  {
346  if (size() != b.size())
347  return size() < b.size();
348  for (unsigned i=0; i<size(); ++i)
349  {
350  if ( (*this)[i]->info() != b[i]->info())
351  return (*this)[i]->info() < b[i]->info();
352  }
353  return _mask < b._mask;
354  }
355  unsigned long _mask;
356  };
357 
358  /* T is the *reducted* function type
359  * S is the storage type of the function
360  * So each instance must know the refMask, and the real return type
361  *
362  * categories of S in use:
363  * boost::function: no reduction performed
364  * bare function pointer
365  * member function pointer: T is the linearized signature
366  */
367  template<typename T, typename S>
369  {
370  public:
371  using ReturnType = typename boost::function_types::result_type<T>::type;
373  : refMask(refMask)
374  {
375 #ifdef QITYPE_TRACK_FUNCTIONTYPE_INSTANCES
376  detail::functionTypeTrack(qi::typeId<S>().name());
377 #endif
378  }
379  void* call(void* storage, void** args, unsigned int argc) override
380  {
381 #if QI_HAS_VARIABLE_LENGTH_ARRAY
382  void* out[argc];
383 #else
384  void* outStatic[8];
385  void** out;
386  if (argc <= 8)
387  out = outStatic;
388  else
389  out = new void*[argc];
390 #endif
391  detail::transformRef(args, out, argc, refMask);
392  void* v = detail::makeCall(*(S*)ptrFromStorage(&storage), (void**)out);
393  // v is storage for type ReturnType we claimed we were
394  // adapt return value if needed
395  if (boost::is_pointer<ReturnType>::value &&
397  static_cast<PointerTypeInterface*>(_resultType)->pointerKind() != PointerTypeInterface::Raw))
398  {
399  // if refMask&1, real return type is some Foo& and v is Foo*
400  // else, return type is Foo with sizeof(Foo) == sizeof(void*) and v is a Foo
401  void* vstorage = _resultType->initializeStorage(
402  (refMask&1)? v: &v);
403  vstorage = _resultType->clone(vstorage);
404  //qiLogWarning("ft") << "Ret deref " << (unsigned long)v <<' ' << vstorage
405  // << ' ' << *(unsigned long*)vstorage;
406  v = vstorage;
407  }
408 #if ! QI_HAS_VARIABLE_LENGTH_ARRAY
409  if (argc > 8)
410  delete[] out;
411 #endif
412  return v;
413  }
414  unsigned long refMask;
415  static FunctionTypeInterfaceEq<T, S>* make(unsigned long refMask, std::vector<TypeInterface*> argsType,
416  TypeInterface* returnType)
417  { // we need to hash/compare on all the arguments
418  std::vector<TypeInterface*> key(argsType);
419  key.push_back(returnType);
420  using FTMap = std::map<InfosKeyMask, FunctionTypeInterfaceEq<T, S>*>;
421  static FTMap* ftMap = 0;
422  static boost::mutex* mutex = 0;
423  QI_THREADSAFE_NEW(ftMap, mutex);
424  boost::mutex::scoped_lock lock(*mutex);
425  FunctionTypeInterfaceEq<T, S>* & fptr = (*ftMap)[InfosKeyMask(key, refMask)];
426  if (!fptr)
427  {
429  fptr->_resultType = returnType;
430  fptr->_argumentsType = argsType;
431  }
432  return fptr;
433  }
435  };
436 
437  namespace detail
438  {
439 
440  // Trick used to avoid instanciating a T
441  template<typename T> struct Ident
442  {
443  };
444 
446  {
447  template<typename T> void operator()(Ident<T>)
448  {
449  qiLogCategory("qitype.functiontypefactory");
450  if (boost::is_reference<T>::value && !boost::is_const<
451  typename boost::remove_reference<T>::type>::value)
452  qiLogWarning() << "Function argument is a non-const reference: " << qi::typeId<T>().name();
453  }
454  };
455  template<typename T> struct remove_constptr
456  {
457  using type = T;
458  };
459 
460 
461  template<typename T> struct remove_constptr<const T*>
462  {
463  using type = T*;
464  };
465 
466  template <typename T>
468 
469  // Fill a vector<TypeInterface*> from a T*
471  {
472  inline fill_arguments(std::vector<TypeInterface*>* target)
473  : target(target) {}
474 
475  template<typename T> void operator()(T*) const
476  {
477  TypeInterface* result = typeOf<
478  typename remove_constptr<
479  typename boost::remove_const<
480  typename boost::remove_reference<T>::type
481  >::type>::type>();
482  target->push_back(result);
483  }
484  std::vector<TypeInterface*>* target;
485  };
486 
487  // build a function pointer or member function pointer type
488  template<typename F, bool Member> struct FunctionPointerSynthetizer
489  {
490  using type = typename boost::function_types::member_function_pointer<F>::type;
491  };
492  template<typename F> struct FunctionPointerSynthetizer<F, false>
493  {
494  using type = typename boost::function_types::function_pointer<F>::type;
495  };
496  // Accept a function pointer or member function pointer
497  template<typename F>
499  {
500  using ArgsType = typename boost::function_types::parameter_types<F>::type;
501  using ResType = typename boost::function_types::result_type<F>::type;
502  TypeInterface* resultType = typeOf<ResType>();
503  std::vector<TypeInterface*> argumentsType;
504  // Generate and store a TypeInterface* for each argument
505  boost::mpl::for_each<
506  boost::mpl::transform_view<ArgsType,
507  boost::add_pointer<
508  boost::remove_const<
509  boost::remove_reference<boost::mpl::_1> > > > >(detail::fill_arguments(&argumentsType));
510  using MapedF = typename EqFunction<F>::type;
511  // regenerate eq function pointer type
512  using EqComponents = typename boost::function_types::components<MapedF>::type;
513  // would have used mpl::if_ but it has laziness issues it seems
514  using EqFunPtr =
516 
517  unsigned long mask = EqFunction<F>::refMask;
518  FunctionTypeInterface* ftype = FunctionTypeInterfaceEq<MapedF, EqFunPtr>::make(mask, argumentsType, resultType);
519 
520  qiLogDebug("qitype.makeAnyFunction") << "bare mask " << (unsigned long)EqFunction<F>::refMask;
521  return AnyFunction(ftype, ftype->clone(ftype->initializeStorage(&func)));
522  }
523 
524  template<typename C, typename R>
526  R (C::*fun)(const AnyArguments&)
527  )
528  {
529  // Pack arguments, call, wrap return value in AnyValue
530  AnyArguments nargs;
531  nargs.args().resize(vargs.size()-1);
532  for (unsigned i=0; i<vargs.size()-1; ++i)
533  nargs.args()[i] = vargs[i+1];
534  C* inst = (C*)vargs.front().rawValue();
535  if (!inst)
536  qiLogWarning("qitype.AnyArgumentsBouncer") << "Null instance";
538  output(), (*inst.*fun)(nargs); // output clones
539  AnyValue* v = new AnyValue(output, false, true); // steal output
540  return AnyReference::fromPtr(v);
541  }
542 
543  template<typename R>
545  boost::function<R (const AnyArguments&)> f
546  )
547  {
548  AnyArguments nargs;
549  if(!vargs.empty())
550  {
551  nargs.args().resize(vargs.size());
552  for (unsigned i=0; i<vargs.size(); ++i)
553  nargs.args()[i] = vargs[i];
554  }
556  output(), f(nargs);
557  AnyValue* v = new AnyValue(output, false, true); // steal output
558  return AnyReference::fromPtr(v);
559  }
560 
561  template<typename C, typename R>
563  {
564  AnyFunction res = AnyFunction::fromDynamicFunction(boost::bind(&bouncer<C, R>, _1, fun));
565  // The signature storage in GO will drop first argument, and bug if none is present
566  const_cast<std::vector<TypeInterface*> &>(res.functionType()->argumentsType()).push_back(typeOf<AnyValue>());
567  return res;
568  }
569 
570  template<typename R>
572  {
573  boost::function<R (const AnyArguments&)> fu = fun;
574  AnyFunction res = AnyFunction::fromDynamicFunction(boost::bind(&bouncerBF<R>, _1, fun));
575  // The signature storage in GO will drop first argument, and bug if none is present
576  const_cast<std::vector<TypeInterface*> &>(res.functionType()->argumentsType()).push_back(typeOf<AnyValue>());
577  return res;
578  }
579 
580  template<typename R> AnyFunction makeAnyFunctionBare(boost::function<R (const AnyArguments&)> fun)
581  {
582  AnyFunction res = AnyFunction::fromDynamicFunction(boost::bind(&bouncerBF<R>, _1, fun));
583  // The signature storage in GO will drop first argument, and bug if none is present
584  const_cast<std::vector<TypeInterface*> &>(res.functionType()->argumentsType()).push_back(typeOf<AnyValue>());
585  return res;
586  }
587 
588  template<typename F> AnyFunction makeAnyFunctionBare(boost::function<F> func)
589  {
590  /* Do not try to reduce anything on a boost::function.
591  * It will bounce to an internal template backend anyway
592  */
593  using ArgsType = typename boost::function_types::parameter_types<F>::type;
594  using ResType = typename boost::function_types::result_type<F>::type;
595  TypeInterface* resultType = typeOf<ResType>();
596  std::vector<TypeInterface*> argumentsType;
597  boost::mpl::for_each<
598  boost::mpl::transform_view<ArgsType,
599  boost::add_pointer<
600  boost::remove_const<
601  boost::remove_reference<boost::mpl::_1> > > > >(detail::fill_arguments(&argumentsType));
602  FunctionTypeInterface* ftype = FunctionTypeInterfaceEq<F, boost::function<F> >::make(0, argumentsType, resultType);
603  return AnyFunction(ftype, new boost::function<F>(func));
604  }
605 
606  // Use helper structures for which template partial specialisation is possible
607  template<typename T> struct AnyFunctionMaker
608  {
609  private:
610  template<typename U>
611  static AnyFunction dispatch(U&& func, ka::true_t is_function_object)
612  {
613  return AnyFunctionMaker<boost::function<ka::Function<T>>>::make(std::forward<U>(func));
614  }
615  template<typename U>
616  static AnyFunction dispatch(U&& func, ka::false_t is_function_object)
617  {
618  return makeAnyFunctionBare(std::forward<U>(func));
619  }
620  public:
623  template<typename U>
624  static AnyFunction make(U&& func)
625  {
626  // If T is a function object (a lambda for example), type-erase it with a boost::function
627  // to allow the type system to handle it.
628  return dispatch(std::forward<U>(func), ka::IsFunctionObject<T>{});
629  }
630  };
631  template<typename T> struct AnyFunctionMaker<T*>
632  {
633  static AnyFunction make(T* func)
634  {
635  return makeAnyFunctionBare(func);
636  }
637  };
638  template<typename R, typename F, typename B>
639  struct AnyFunctionMaker<boost::_bi::bind_t<R, F, B> >
640  {
641  static AnyFunction make(boost::_bi::bind_t<R, F, B> v)
642  {
643  using CompatType =
644  typename boost::function<typename boost_bind_function_type<boost::_bi::bind_t<R, F, B>>::type>;
645  CompatType f = v;
646  return AnyFunction::from(f);
647  }
648  };
649  template<typename T> struct AnyFunctionMaker<boost::function<T> >
650  {
651  static AnyFunction make(boost::function<T> func)
652  {
653  static_assert(sizeof(boost::function<T>) == sizeof(boost::function<void()>),
654  "boost::functions are not all the same size");
655  AnyFunction res = detail::makeAnyFunctionBare(func);
656  return res;
657  }
658  };
659  template<typename T> struct AnyFunctionMaker<const T&>
660  : public AnyFunctionMaker<T> {};
661  template<> struct AnyFunctionMaker<AnyFunction>
662  {
663  static AnyFunction make(AnyFunction func)
664  {
665  return func;
666  }
667  };
668  }
669 
670  template<typename T>
672  {
673  // If an lvalue is passed then T is deduced to be U&, so remove the reference.
674  return detail::AnyFunctionMaker<ka::RemoveRef<T>>::make(std::forward<T>(f));
675  }
676 
677  namespace detail
678  {
679  template<typename T> struct Pointer
680  {
681  static T* pointer(T& t)
682  {
683  return &t;
684  }
685  };
686  template<typename T> struct Pointer<T*>
687  {
688  static T* pointer(T* & t)
689  {
690  return t;
691  }
692  };
693  }
694 
695  template<typename F, typename C>
696  AnyFunction AnyFunction::from(F func, C instance)
697  {
698  /* Taking a AnyFunction of F will likely imply a typeOf<C> which is
699  * unnecessary. So use a fake class in signature.
700  */
701  using Result = typename boost::function_types::result_type<F>::type;
702  using Args = typename boost::function_types::parameter_types<F, boost::mpl::identity<boost::mpl::_1> >::type;
703  using ArgsNoClass = typename boost::mpl::pop_front<Args>::type;
704  using ArgsFakeClass = typename boost::mpl::push_front<ArgsNoClass, detail::Class&>::type;
705  using ComponentsFaked = typename boost::mpl::push_front<ArgsFakeClass, Result>::type;
706  using MethodTypeFaked = typename boost::function_types::member_function_pointer<ComponentsFaked>::type;
707  MethodTypeFaked newFunk = *(MethodTypeFaked*)(void*)&func;
708  AnyFunction res = AnyFunction::from(newFunk);
709 
710  // Dynamic-cast instance to expected pointer type.
711  using FirstArg = typename boost::mpl::at_c<Args, 0>::type;
712  // Get expected
713  FirstArg* ptr = dynamic_cast<FirstArg*>(detail::Pointer<C>::pointer(instance));
714  if (!ptr && instance)
715  throw std::runtime_error("makeAnyFunction: failed to dynamic_cast bound value to expected type");
716  res.prependArgument((void*)(const void*)ptr);
717  return res;
718  }
719 
720 }
721 #endif // _QITYPE_DETAIL_ANYFUNCTIONFACTORY_HXX_
typename boost::function_types::result_type< F >::type Result
void transformRef(void **args, void **out, unsigned int sz, unsigned long refMask)
static const unsigned long refMask
virtual void * ptrFromStorage(void **)=0
typename boost::function_types::result_type< T >::type ReturnType
typename boost::function_types::components< F >::type Components
#define makeCall_(n, argstypedecl, argstype, argsdecl, argsues, comma)
AnyValueVector & args()
#define QI_API
Definition: api.hpp:33
typename boost::mpl::push_front< EqComponentsInt, EqResult >::type EqComponents
bool operator<(const InfosKeyMask &b) const
FunctionTypeInterfaceEq(unsigned long refMask)
#define qiLogCategory(Cat)
Definition: log.hpp:53
typename boost::function_types::parameter_types< F >::type MethodArguments
AnyFunction makeAnyFunctionBare(F func)
#define qiLogDebug(...)
Definition: log.hpp:76
virtual TypeKind kind()
Definition: type.hxx:99
typename boost::mpl::if_< typename boost::is_fundamental< T >::type, void *, T >::type rType
typename boost::mpl::if_< typename boost::is_fundamental< T >::type, void *, T >::type type
typename boost::is_reference< T >::type isReference
typename remove_constptr< T >::type remove_constptr_t
typename boost::mpl::transform< Arguments, EqType< boost::mpl::_1 > >::type EqArguments
FunctionTypeInterface * functionType() const
Definition: anyfunction.hxx:82
#define QI_THREADSAFE_NEW(...)
Safe static initialization of variables.
Definition: atomic.hpp:374
_QI_BOUNCE_TYPE_METHODS(DefaultTypeImplMethods< S >)
virtual void * initializeStorage(void *ptr=nullptr)=0
typename boost::function_types::function_type< EqComponents >::type type
#define qiLogWarning(...)
Log in warning mode.
Definition: log.hpp:109
fill_arguments(std::vector< TypeInterface * > *target)
#define makeCall(n, argstypedecl, argstype, argsdecl, argsues, comma)
const std::vector< TypeInterface * > & argumentsType()
Definition: anyfunction.hxx:25
typename boost::function_types::parameter_types< F >::type Arguments
typename EqType< Result >::rType EqResult
AnyReference bouncer(const AnyReferenceVector &vargs, R(C::*fun)(const AnyArguments &))
A function with AnyArguments as its sole argument will behave as if AnyFunction::fromDynamicFunction ...
std::vector< AnyReference > AnyReferenceVector
typename boost::is_reference< T >::type isReference
typename boost::function_types::components< F >::type Components
typename boost::function_types::member_function_pointer< EqComponents >::type type
typename boost::function_types::result_type< F >::type Result
const AnyFunction & prependArgument(void *value) const
Prepend extra argument value to argument list.
TypeInterface * _resultType
Definition: anyfunction.hpp:83
static void assignAnyRef(AnyReference *ref, X &&any)
static AnyFunction fromDynamicFunction(DynamicFunction f)
typename EqType< Result >::rType EqResult
static const unsigned long refMask
TypeInterface * typeOf()
Definition: type.hxx:94
typename boost::mpl::pop_front< MethodArguments >::type Arguments
static AnyFunction from(F &&func)
typename boost::mpl::push_front< EqArguments, EqResult >::type EqComponents
typename boost::mpl::transform< Arguments, EqType< boost::mpl::_1 >>::type EqArguments
AnyReference bouncerBF(const AnyReferenceVector &vargs, boost::function< R(const AnyArguments &)> f)
static FunctionTypeInterfaceEq< T, S > * make(unsigned long refMask, std::vector< TypeInterface * > argsType, TypeInterface *returnType)
void operator,(AnyReferenceCopy &g, T &&any)
typename boost::function_types::member_function_pointer< F >::type type
static AnyReference from(const T &ref)
static AnyReference fromPtr(const T *ptr)
virtual void * clone(void *)=0
Allocate a storage and copy the value given as an argument.
std::vector< TypeInterface * > _argumentsType
Definition: anyfunction.hpp:85
typename boost::mpl::push_front< EqArguments, detail::Class & >::type EqComponentsInt
InfosKeyMask(const std::vector< TypeInterface * > &b, unsigned long mask)
typename boost::function_types::function_pointer< F >::type type
static void assignAnyRef(AnyReference *ref, T *any)
void * call(void *storage, void **args, unsigned int argc) override
std::enable_if< std::is_function< RF >::value, boost::function< RF > >::type bind(AF &&fun, Arg0 &&arg0, Args &&...args)
Definition: trackable.hxx:308
static T * pointer(T &t)
#define QI_GEN(f)
Definition: preproc.hpp:476
std::vector< TypeInterface * > * target