- Aldebaran documentation |
- C++ Libraries |
- index

libqi-api 2.8.7.4

- Main Page
- Related Pages
- Namespaces
- Classes
- Files
- Examples

- File List
- File Members

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
233 class AnyReferenceCopy: public AnyReference
234 {
235 public:
236 AnyReferenceCopy &operator()() { return *this; }
237 };
238
239 template <typename T>
240 struct AssignAnyRef
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 }
280 QI_GEN(makeCall)
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 }
306 QI_GEN(makeCall)
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 }
318 QI_GEN(makeCall)
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
328 QI_GEN(makeCall_)
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>
368 class FunctionTypeInterfaceEq: public FunctionTypeInterface
369 {
370 public:
371 using ReturnType = typename boost::function_types::result_type<T>::type;
372 FunctionTypeInterfaceEq(unsigned long refMask)
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 &&
396 (_resultType->kind() != TypeKind_Pointer ||
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 {
428 fptr = new FunctionTypeInterfaceEq<T, S>(refMask);
429 fptr->_resultType = returnType;
430 fptr->_argumentsType = argsType;
431 }
432 return fptr;
433 }
434 _QI_BOUNCE_TYPE_METHODS(DefaultTypeImplMethods<S>);
435 };
436
437 namespace detail
438 {
439
440 // Trick used to avoid instanciating a T
441 template<typename T> struct Ident
442 {
443 };
444
445 struct checkForNonConstRef
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>
467 using remove_constptr_t = typename remove_constptr<T>::type;
468
469 // Fill a vector<TypeInterface*> from a T*
470 struct fill_arguments
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>
498 AnyFunction makeAnyFunctionBare(F func)
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 =
515 typename FunctionPointerSynthetizer<EqComponents, boost::is_member_function_pointer<F>::value>::type;
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>
525 AnyReference bouncer(const AnyReferenceVector& vargs,
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";
537 detail::AnyReferenceCopy output;
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>
544 AnyReference bouncerBF(const AnyReferenceVector& vargs,
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 }
555 detail::AnyReferenceCopy output;
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>
562 AnyFunction makeAnyFunctionBare(R (C::*fun)(const AnyArguments&))
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>
571 AnyFunction makeAnyFunctionBare(R (*fun)(const AnyArguments&))
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>
671 AnyFunction AnyFunction::from(T&& f)
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_
qi::detail::EqFunctionBare::Result
typename boost::function_types::result_type< F >::type Result
Definition: anyfunctionfactory.hxx:168
qi::detail::transformRef
void transformRef(void **args, void **out, unsigned int sz, unsigned long refMask)
Definition: anyfunctionfactory.hxx:212
qi::detail::EqType< void >::isReference
boost::false_type isReference
Definition: anyfunctionfactory.hxx:92
qi::detail::EqMemberFunction::refMask
static const unsigned long refMask
Definition: anyfunctionfactory.hxx:197
qi::TypeInterface::ptrFromStorage
virtual void * ptrFromStorage(void **)=0
qi::FunctionTypeInterfaceEq::ReturnType
typename boost::function_types::result_type< T >::type ReturnType
Definition: anyfunctionfactory.hxx:371
qi::detail::EqType< T * >::type
void * type
Definition: anyfunctionfactory.hxx:137
qi::detail::checkForNonConstRef
Definition: anyfunctionfactory.hxx:445
qi::AnyValue
Definition: anyvalue.hpp:19
qi::detail::EqType< float >::type
float type
Definition: anyfunctionfactory.hxx:104
qi::detail::EqFunctionBare::Components
typename boost::function_types::components< F >::type Components
Definition: anyfunctionfactory.hxx:165
qi::detail::remove_constptr::type
T type
Definition: anyfunctionfactory.hxx:457
makeCall_
#define makeCall_(n, argstypedecl, argstype, argsdecl, argsues, comma)
Definition: anyfunctionfactory.hxx:321
qi::AnyArguments::args
AnyValueVector & args()
Definition: anyfunction.hpp:135
QI_API
#define QI_API
Definition: api.hpp:33
qi::detail::EqMemberFunction::EqComponents
typename boost::mpl::push_front< EqComponentsInt, EqResult >::type EqComponents
Definition: anyfunctionfactory.hxx:195
qi::detail::fill_arguments
Definition: anyfunctionfactory.hxx:470
qi::InfosKeyMask::operator<
bool operator<(const InfosKeyMask &b) const
Definition: anyfunctionfactory.hxx:344
qi::FunctionTypeInterfaceEq::FunctionTypeInterfaceEq
FunctionTypeInterfaceEq(unsigned long refMask)
Definition: anyfunctionfactory.hxx:372
qi::detail::Class
Definition: anyfunctionfactory.hxx:57
qiLogCategory
#define qiLogCategory(Cat)
Definition: log.hpp:53
qi::detail::EqMemberFunction::MethodArguments
typename boost::function_types::parameter_types< F >::type MethodArguments
Definition: anyfunctionfactory.hxx:186
qi::detail::makeAnyFunctionBare
AnyFunction makeAnyFunctionBare(F func)
Definition: anyfunctionfactory.hxx:498
qi::detail::EqMemberFunction
Definition: anyfunctionfactory.hxx:181
qi::AnyFunction
Definition: anyfunction.hpp:149
qiLogDebug
#define qiLogDebug(...)
Definition: log.hpp:76
qi::AnyReference
Definition: anyreference.hpp:360
qi::TypeInterface::kind
virtual TypeKind kind()
Definition: type.hxx:99
qi::detail::EqTypeBase< T, true >::rType
typename boost::mpl::if_< typename boost::is_fundamental< T >::type, void *, T >::type rType
Definition: anyfunctionfactory.hxx:78
qi::InfosKeyMask
Definition: anyfunctionfactory.hxx:339
qi::detail::remove_constptr
Definition: anyfunctionfactory.hxx:455
qi::detail::checkForNonConstRef::operator()
void operator()(Ident< T >)
Definition: anyfunctionfactory.hxx:447
qi::detail::EqTypeBase< T, true >::type
typename boost::mpl::if_< typename boost::is_fundamental< T >::type, void *, T >::type type
Definition: anyfunctionfactory.hxx:77
qi::detail::EqType< T const & >::type
void * type
Definition: anyfunctionfactory.hxx:126
qi::detail::EqTypeBase< T, true >::isReference
typename boost::is_reference< T >::type isReference
Definition: anyfunctionfactory.hxx:79
qi::detail::remove_constptr_t
typename remove_constptr< T >::type remove_constptr_t
Definition: anyfunctionfactory.hxx:467
qi::detail::EqMemberFunction::EqArguments
typename boost::mpl::transform< Arguments, EqType< boost::mpl::_1 > >::type EqArguments
Definition: anyfunctionfactory.hxx:191
qi::AnyFunction::functionType
FunctionTypeInterface * functionType() const
Definition: anyfunction.hxx:82
QI_THREADSAFE_NEW
#define QI_THREADSAFE_NEW(...)
Safe static initialization of variables.
Definition: atomic.hpp:374
qi::detail::EqType< float >::isReference
boost::false_type isReference
Definition: anyfunctionfactory.hxx:106
qi::detail::EqTypeBase< T, sizeof(T)==sizeof(void *)>::rType
T rType
Definition: anyfunctionfactory.hxx:69
qi::FunctionTypeInterfaceEq::_QI_BOUNCE_TYPE_METHODS
_QI_BOUNCE_TYPE_METHODS(DefaultTypeImplMethods< S >)
qi::TypeInterface::initializeStorage
virtual void * initializeStorage(void *ptr=nullptr)=0
qi::detail::EqFunctionBare::type
typename boost::function_types::function_type< EqComponents >::type type
Definition: anyfunctionfactory.hxx:178
qiLogWarning
#define qiLogWarning(...)
Log in warning mode.
Definition: log.hpp:109
qi::detail::EqType< T const & >::rType
void * rType
Definition: anyfunctionfactory.hxx:127
qi::detail::EqTypeBase::dbgTag
static const int dbgTag
Definition: anyfunctionfactory.hxx:71
qi::detail::EqType< T const & >::isReference
boost::true_type isReference
Definition: anyfunctionfactory.hxx:128
qi::detail::fill_arguments::fill_arguments
fill_arguments(std::vector< TypeInterface * > *target)
Definition: anyfunctionfactory.hxx:472
qi::detail::AnyReferenceCopy
Definition: anyfunctionfactory.hxx:233
qi::detail::EqType< T & >::type
void * type
Definition: anyfunctionfactory.hxx:118
qi::TypeInterface
Definition: typeinterface.hpp:129
makeCall
#define makeCall(n, argstypedecl, argstype, argsdecl, argsues, comma)
Definition: anyfunctionfactory.hxx:309
qi::CallableTypeInterface::argumentsType
const std::vector< TypeInterface * > & argumentsType()
Definition: anyfunction.hxx:25
qi::detail::EqFunctionBare::Arguments
typename boost::function_types::parameter_types< F >::type Arguments
Definition: anyfunctionfactory.hxx:167
qi::detail::Pointer
Definition: anyfunctionfactory.hxx:679
qi::detail::remove_constptr< const T * >::type
T * type
Definition: anyfunctionfactory.hxx:463
qi::detail::EqFunctionBare::EqResult
typename EqType< Result >::rType EqResult
Definition: anyfunctionfactory.hxx:172
qi::detail::EqFunction
Definition: anyfunctionfactory.hxx:202
qi::detail::bouncer
AnyReference bouncer(const AnyReferenceVector &vargs, R(C::*fun)(const AnyArguments &))
Definition: anyfunctionfactory.hxx:525
qi::detail::EqType< double >::isReference
boost::false_type isReference
Definition: anyfunctionfactory.hxx:99
qi::detail::EqType< double >::rType
double rType
Definition: anyfunctionfactory.hxx:98
qi::detail::EqType< T & >::rType
void * rType
Definition: anyfunctionfactory.hxx:119
qi::AnyArguments
A function with AnyArguments as its sole argument will behave as if AnyFunction::fromDynamicFunction ...
Definition: anyfunction.hpp:128
qi::FunctionTypeInterface
Definition: anyfunction.hpp:88
anyvalue.hpp
qi::AnyReferenceVector
std::vector< AnyReference > AnyReferenceVector
Definition: anyreference.hpp:26
qi::detail::EqType< float >::rType
float rType
Definition: anyfunctionfactory.hxx:105
qi::detail::Ident
Definition: anyfunctionfactory.hxx:441
qi::TypeKind_Pointer
Definition: fwd.hpp:64
qi::detail::EqType< T * >::isReference
boost::true_type isReference
Definition: anyfunctionfactory.hxx:139
qi::InfosKeyMask::_mask
unsigned long _mask
Definition: anyfunctionfactory.hxx:355
qi::detail::EqTypeBase< T, sizeof(T)==sizeof(void *)>::type
T type
Definition: anyfunctionfactory.hxx:68
qi::detail::EqTypeBase< T, sizeof(T)==sizeof(void *)>::isReference
typename boost::is_reference< T >::type isReference
Definition: anyfunctionfactory.hxx:70
qi::DefaultTypeImplMethods
Definition: typeimpl.hxx:228
qi::detail::FunctionPointerSynthetizer
Definition: anyfunctionfactory.hxx:488
qi::detail::fill_arguments::operator()
void operator()(T *) const
Definition: anyfunctionfactory.hxx:475
qi::detail::EqMemberFunction::Components
typename boost::function_types::components< F >::type Components
Definition: anyfunctionfactory.hxx:183
qi::detail::EqFunctionBare
Definition: anyfunctionfactory.hxx:163
qi::detail::EqType< bool >::type
bool type
Definition: anyfunctionfactory.hxx:111
qi::detail::Pointer< T * >::pointer
static T * pointer(T *&t)
Definition: anyfunctionfactory.hxx:688
qi::detail::EqMemberFunction::type
typename boost::function_types::member_function_pointer< EqComponents >::type type
Definition: anyfunctionfactory.hxx:196
qi::detail::EqMemberFunction::Result
typename boost::function_types::result_type< F >::type Result
Definition: anyfunctionfactory.hxx:190
qi::AnyFunction::prependArgument
const AnyFunction & prependArgument(void *value) const
Prepend extra argument value to argument list.
qi::CallableTypeInterface::_resultType
TypeInterface * _resultType
Definition: anyfunction.hpp:83
qi::detail::EqType< double >::type
double type
Definition: anyfunctionfactory.hxx:97
qi::detail::AssignAnyRef::assignAnyRef
static void assignAnyRef(AnyReference *ref, X &&any)
Definition: anyfunctionfactory.hxx:243
qi::detail::EqType< void >::type
void type
Definition: anyfunctionfactory.hxx:90
qi::AnyFunction::fromDynamicFunction
static AnyFunction fromDynamicFunction(DynamicFunction f)
qi::detail::EqMemberFunction::EqResult
typename EqType< Result >::rType EqResult
Definition: anyfunctionfactory.hxx:192
qi::detail::EqFunctionBare::refMask
static const unsigned long refMask
Definition: anyfunctionfactory.hxx:176
qi::detail::EqType
Definition: anyfunctionfactory.hxx:84
atomic.hpp
qi::detail::AssignAnyRef
Definition: anyfunctionfactory.hxx:240
qi::PointerTypeInterface
Definition: typeinterface.hpp:137
qi::typeOf
TypeInterface * typeOf()
Definition: type.hxx:94
qi::log::env::QI_DEFAULT_LOGHANDLER::name
char const *const name
qi::detail::EqMemberFunction::Arguments
typename boost::mpl::pop_front< MethodArguments >::type Arguments
Definition: anyfunctionfactory.hxx:188
qi::AnyFunction::from
static AnyFunction from(F &&func)
qi::detail::EqType< bool >::isReference
boost::false_type isReference
Definition: anyfunctionfactory.hxx:113
qi::detail::EqFunctionBare::EqComponents
typename boost::mpl::push_front< EqArguments, EqResult >::type EqComponents
Definition: anyfunctionfactory.hxx:173
qi::detail::EqFunctionBare::EqArguments
typename boost::mpl::transform< Arguments, EqType< boost::mpl::_1 >>::type EqArguments
Definition: anyfunctionfactory.hxx:171
qi::detail::bouncerBF
AnyReference bouncerBF(const AnyReferenceVector &vargs, boost::function< R(const AnyArguments &)> f)
Definition: anyfunctionfactory.hxx:544
qi::FunctionTypeInterfaceEq::make
static FunctionTypeInterfaceEq< T, S > * make(unsigned long refMask, std::vector< TypeInterface * > argsType, TypeInterface *returnType)
Definition: anyfunctionfactory.hxx:415
qi::detail::EqType< void >::rType
void * rType
Definition: anyfunctionfactory.hxx:91
qi::detail::operator,
void operator,(AnyReferenceCopy &g, T &&any)
Definition: anyfunctionfactory.hxx:260
qi::detail::FunctionPointerSynthetizer::type
typename boost::function_types::member_function_pointer< F >::type type
Definition: anyfunctionfactory.hxx:490
qi::detail::AnyReferenceCopy::operator()
AnyReferenceCopy & operator()()
Definition: anyfunctionfactory.hxx:236
qi::PointerTypeInterface::Raw
Definition: typeinterface.hpp:142
qi::detail::EqTypeBase
Definition: anyfunctionfactory.hxx:66
qi::detail::AnyReferenceBase::from
static AnyReference from(const T &ref)
Definition: anyreference.hxx:64
qi::detail::AnyReferenceBase::fromPtr
static AnyReference fromPtr(const T *ptr)
Definition: anyreference.hxx:54
qi::TypeInterface::clone
virtual void * clone(void *)=0
Allocate a storage and copy the value given as an argument.
qi::detail::EqType< bool >::rType
bool rType
Definition: anyfunctionfactory.hxx:112
qi::detail::EqType< T * >::rType
void * rType
Definition: anyfunctionfactory.hxx:138
qi::CallableTypeInterface::_argumentsType
std::vector< TypeInterface * > _argumentsType
Definition: anyfunction.hpp:85
qi::detail::EqMemberFunction::EqComponentsInt
typename boost::mpl::push_front< EqArguments, detail::Class & >::type EqComponentsInt
Definition: anyfunctionfactory.hxx:194
qi::InfosKeyMask::InfosKeyMask
InfosKeyMask(const std::vector< TypeInterface * > &b, unsigned long mask)
Definition: anyfunctionfactory.hxx:342
qi::detail::FunctionPointerSynthetizer< F, false >::type
typename boost::function_types::function_pointer< F >::type type
Definition: anyfunctionfactory.hxx:494
qi::detail::AssignAnyRef< T * >::assignAnyRef
static void assignAnyRef(AnyReference *ref, T *any)
Definition: anyfunctionfactory.hxx:253
qi::FunctionTypeInterfaceEq::call
void * call(void *storage, void **args, unsigned int argc) override
Definition: anyfunctionfactory.hxx:379
qi::FunctionTypeInterfaceEq
Definition: anyfunctionfactory.hxx:368
qi::detail::EqType< T & >::isReference
boost::true_type isReference
Definition: anyfunctionfactory.hxx:120
qi::bind
std::enable_if< std::is_function< RF >::value, boost::function< RF > >::type bind(AF &&fun, Arg0 &&arg0, Args &&...args)
Definition: trackable.hxx:308
qi::FunctionTypeInterfaceEq::refMask
unsigned long refMask
Definition: anyfunctionfactory.hxx:414
qi::detail::Pointer::pointer
static T * pointer(T &t)
Definition: anyfunctionfactory.hxx:681
QI_GEN
#define QI_GEN(f)
Definition: preproc.hpp:476
qi::detail::fill_arguments::target
std::vector< TypeInterface * > * target
Definition: anyfunctionfactory.hxx:484