7 #ifndef _QITYPE_DETAIL_ANYFUNCTIONFACTORY_HXX_
8 #define _QITYPE_DETAIL_ANYFUNCTIONFACTORY_HXX_
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>
35 #include <ka/typetraits.hpp>
65 template <
typename T,
bool isWordSize>
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;
121 static const int dbgTag = 2;
124 template <
typename T>
struct EqType<T const &>
129 static const int dbgTag = 3;
134 template <
typename T>
140 static const int dbgTag = 4;
144 template<
typename S,
typename I,
int p>
145 struct RefMasqBuilderHelper
147 using type =
typename boost::mpl::deref<I>::type;
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;
154 template<
typename S,
int p>
155 struct RefMasqBuilderHelper<S, typename boost::mpl::end<S>::type, p>
157 static const unsigned long val = 0;
165 using Components =
typename boost::function_types::components<F>::type;
167 using Arguments =
typename boost::function_types::parameter_types<F>::type;
168 using Result =
typename boost::function_types::result_type<F>::type;
173 using EqComponents =
typename boost::mpl::push_front<EqArguments, EqResult>::type;
177 typename boost::mpl::begin<Components>::type, 0>::val;
178 using type =
typename boost::function_types::function_type<EqComponents>::type;
183 using Components =
typename boost::function_types::components<F>::type;
188 using Arguments =
typename boost::mpl::pop_front<MethodArguments>::type;
190 using Result =
typename boost::function_types::result_type<F>::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;
198 typename boost::mpl::begin<Components>::type, 0>::val;
203 public boost::mpl::if_<typename boost::is_member_function_pointer<F>::type,
205 EqFunctionBare<F> >::type
212 inline void transformRef(
void** args,
void** out,
unsigned int sz,
unsigned long refMask)
214 for (
unsigned i=0; i<sz; ++i)
216 if (refMask & (1 << (i+1)))
239 template <
typename T>
245 using CopyType =
typename std::decay<T>::type;
246 *ref =
AnyReference(qi::typeOf<T>(),
new CopyType(std::forward<X>(any)));
250 template <
typename T>
259 template <
typename T>
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) \
276 detail::AnyReferenceCopy val; \
277 val(), f(BOOST_PP_REPEAT(n, callArg, _)); \
278 return val.rawValue(); \
284 #define STATIC_IF_SAFE
286 #define STATIC_IF_SAFE static
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])
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) \
302 BOOST_PP_REPEAT(n, declType, _) detail::AnyReferenceCopy val; \
303 val(), f(BOOST_PP_REPEAT(n, callArgBF, _)); \
304 return val.rawValue(); \
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) \
313 detail::AnyReferenceCopy val; \
314 Class* cptr = *(Class**)instance; \
315 val(), ((*cptr).*f)(BOOST_PP_REPEAT(n, callArg, _)); \
316 return val.rawValue(); \
321 #define makeCall_(n, argstypedecl, argstype, argsdecl, argsues, comma) \
322 template <typename R comma argstypedecl> \
323 void* makeCall(R (Class::*f)(argstype), void** args) \
325 return makeCall(f, args[0], args + 1); \
332 #ifdef QITYPE_TRACK_FUNCTIONTYPE_INSTANCES
334 void QI_API functionTypeTrack(
const std::string& functionName);
335 void QI_API functionTypeDump();
346 if (size() != b.size())
347 return size() < b.size();
348 for (
unsigned i=0; i<size(); ++i)
350 if ( (*
this)[i]->info() != b[i]->info())
351 return (*
this)[i]->info() < b[i]->info();
367 template<
typename T,
typename S>
371 using ReturnType =
typename boost::function_types::result_type<T>::type;
375 #ifdef QITYPE_TRACK_FUNCTIONTYPE_INSTANCES
376 detail::functionTypeTrack(qi::typeId<S>().
name());
379 void*
call(
void* storage,
void** args,
unsigned int argc)
override
381 #if QI_HAS_VARIABLE_LENGTH_ARRAY
389 out =
new void*[argc];
395 if (boost::is_pointer<ReturnType>::value &&
408 #if ! QI_HAS_VARIABLE_LENGTH_ARRAY
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;
424 boost::mutex::scoped_lock lock(*mutex);
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();
466 template <
typename T>
479 typename boost::remove_const<
480 typename boost::remove_reference<T>::type
482 target->push_back(result);
490 using type =
typename boost::function_types::member_function_pointer<F>::type;
494 using type =
typename boost::function_types::function_pointer<F>::type;
500 using ArgsType =
typename boost::function_types::parameter_types<F>::type;
501 using ResType =
typename boost::function_types::result_type<F>::type;
503 std::vector<TypeInterface*> argumentsType;
505 boost::mpl::for_each<
506 boost::mpl::transform_view<ArgsType,
512 using EqComponents =
typename boost::function_types::components<MapedF>::type;
524 template<
typename C,
typename R>
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();
536 qiLogWarning(
"qitype.AnyArgumentsBouncer") <<
"Null instance";
538 output(), (*inst.*fun)(nargs);
551 nargs.
args().resize(vargs.size());
552 for (
unsigned i=0; i<vargs.size(); ++i)
553 nargs.
args()[i] = vargs[i];
561 template<
typename C,
typename R>
573 boost::function<R (const AnyArguments&)> fu = fun;
593 using ArgsType =
typename boost::function_types::parameter_types<F>::type;
594 using ResType =
typename boost::function_types::result_type<F>::type;
596 std::vector<TypeInterface*> argumentsType;
597 boost::mpl::for_each<
598 boost::mpl::transform_view<ArgsType,
603 return AnyFunction(ftype,
new boost::function<F>(func));
607 template<
typename T>
struct AnyFunctionMaker
611 static AnyFunction dispatch(U&& func, ka::true_t is_function_object)
613 return AnyFunctionMaker<boost::function<ka::Function<T>>>::make(std::forward<U>(func));
616 static AnyFunction dispatch(U&& func, ka::false_t is_function_object)
624 static AnyFunction make(U&& func)
628 return dispatch(std::forward<U>(func), ka::IsFunctionObject<T>{});
631 template<
typename T>
struct AnyFunctionMaker<T*>
633 static AnyFunction make(T* func)
638 template<
typename R,
typename F,
typename B>
639 struct AnyFunctionMaker<boost::_bi::bind_t<R, F, B> >
641 static AnyFunction make(boost::_bi::bind_t<R, F, B> v)
644 typename boost::function<typename boost_bind_function_type<boost::_bi::bind_t<R, F, B>>::type>;
649 template<
typename T>
struct AnyFunctionMaker<boost::function<T> >
651 static AnyFunction make(boost::function<T> func)
653 static_assert(
sizeof(boost::function<T>) ==
sizeof(boost::function<
void()>),
654 "boost::functions are not all the same size");
659 template<
typename T>
struct AnyFunctionMaker<const T&>
660 :
public AnyFunctionMaker<T> {};
661 template<>
struct AnyFunctionMaker<AnyFunction>
663 static AnyFunction make(AnyFunction func)
674 return detail::AnyFunctionMaker<ka::RemoveRef<T>>::make(std::forward<T>(f));
695 template<
typename F,
typename C>
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;
711 using FirstArg =
typename boost::mpl::at_c<Args, 0>::type;
714 if (!ptr && instance)
715 throw std::runtime_error(
"makeAnyFunction: failed to dynamic_cast bound value to expected type");
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)
boost::false_type isReference
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)
typename boost::mpl::push_front< EqComponentsInt, EqResult >::type EqComponents
bool operator<(const InfosKeyMask &b) const
FunctionTypeInterfaceEq(unsigned long refMask)
#define qiLogCategory(Cat)
typename boost::function_types::parameter_types< F >::type MethodArguments
AnyFunction makeAnyFunctionBare(F func)
typename boost::mpl::if_< typename boost::is_fundamental< T >::type, void *, T >::type rType
void operator()(Ident< T >)
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
#define QI_THREADSAFE_NEW(...)
Safe static initialization of variables.
boost::false_type isReference
_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.
boost::true_type isReference
fill_arguments(std::vector< TypeInterface * > *target)
#define makeCall(n, argstypedecl, argstype, argsdecl, argsues, comma)
const std::vector< TypeInterface * > & argumentsType()
typename boost::function_types::parameter_types< F >::type Arguments
typename EqType< Result >::rType EqResult
AnyReference bouncer(const AnyReferenceVector &vargs, R(C::*fun)(const AnyArguments &))
boost::false_type isReference
A function with AnyArguments as its sole argument will behave as if AnyFunction::fromDynamicFunction ...
std::vector< AnyReference > AnyReferenceVector
boost::true_type isReference
typename boost::is_reference< T >::type isReference
void operator()(T *) const
typename boost::function_types::components< F >::type Components
static T * pointer(T *&t)
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
static void assignAnyRef(AnyReference *ref, X &&any)
static AnyFunction fromDynamicFunction(DynamicFunction f)
typename EqType< Result >::rType EqResult
static const unsigned long refMask
typename boost::mpl::pop_front< MethodArguments >::type Arguments
static AnyFunction from(F &&func)
boost::false_type isReference
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
AnyReferenceCopy & operator()()
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
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
boost::true_type isReference
std::enable_if< std::is_function< RF >::value, boost::function< RF > >::type bind(AF &&fun, Arg0 &&arg0, Args &&...args)
std::vector< TypeInterface * > * target