7 #ifndef _QITYPE_DETAILS_ANYFUNCTIONFACTORY_HXX_
8 #define _QITYPE_DETAILS_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>
64 template <
typename T,
bool isWordSize>
76 typedef typename boost::mpl::if_<typename boost::is_fundamental<T>::type,
void*, T>
::type type;
77 typedef typename boost::mpl::if_<typename boost::is_fundamental<T>::type,
void*, T>
::type rType;
120 static const int dbgTag = 2;
123 template <
typename T>
struct EqType<T const &>
128 static const int dbgTag = 3;
133 template <
typename T>
139 static const int dbgTag = 4;
143 template<
typename S,
typename I,
int p>
144 struct RefMasqBuilderHelper
146 typedef typename boost::mpl::deref<I>::type type;
148 static const unsigned long vSelf = isRef << p;
149 static const unsigned long val = vSelf + RefMasqBuilderHelper<S,
150 typename boost::mpl::next<I>::type, p+1>::val;
153 template<
typename S,
int p>
154 struct RefMasqBuilderHelper<S, typename boost::mpl::end<S>::type, p>
156 static const unsigned long val = 0;
164 typedef typename boost::function_types::components<F>::type
Components;
166 typedef typename boost::function_types::parameter_types<F>::type
Arguments;
167 typedef typename boost::function_types::result_type<F>::type
Result;
170 typedef typename boost::mpl::transform<
Arguments,
173 typedef typename boost::mpl::push_front<EqArguments, EqResult>::type
EqComponents;
177 typename boost::mpl::begin<Components>::type, 0>::val;
178 typedef typename boost::function_types::function_type<EqComponents>::type
type;
183 typedef typename boost::function_types::components<F>::type
Components;
188 typedef typename boost::mpl::pop_front<MethodArguments>::type
Arguments;
190 typedef typename boost::function_types::result_type<F>::type
Result;
191 typedef typename boost::mpl::transform<
Arguments,
195 typedef typename boost::mpl::push_front<EqArguments, detail::Class&>::type
EqComponentsInt;
196 typedef typename boost::mpl::push_front<EqComponentsInt, EqResult>::type
EqComponents;
197 typedef typename boost::function_types::member_function_pointer<EqComponents>::type
type;
199 typename boost::mpl::begin<Components>::type, 0>::val;
204 public boost::mpl::if_<typename boost::is_member_function_pointer<F>::type,
206 EqFunctionBare<F> >::type
213 inline void transformRef(
void** args,
void** out,
unsigned int sz,
unsigned long refMask)
215 for (
unsigned i=0; i<sz; ++i)
217 if (refMask & (1 << (i+1)))
250 #define callArg(z, n, _) \
251 BOOST_PP_COMMA_IF(n) * (typename boost::remove_reference<P##n>::type*)args[n]
252 #define makeCall(n, argstypedecl, argstype, argsdecl, argsues, comma) \
253 template <typename R comma argstypedecl> \
254 void* makeCall(R (*f)(argstype), void** args) \
256 detail::AnyReferenceCopy val; \
257 val(), f(BOOST_PP_REPEAT(n, callArg, _)); \
258 return val.rawValue(); \
264 #define STATIC_IF_SAFE
266 #define STATIC_IF_SAFE static
271 #define declType(z, n, _) \
272 STATIC_IF_SAFE TypeInterface* type_##n = \
273 typeOf<typename boost::remove_reference<P##n>::type>();
274 #define callArgBF(z, n, _) \
275 BOOST_PP_COMMA_IF(n) * (typename boost::remove_reference<P##n>::type*) \
276 type_##n->ptrFromStorage(&args[n])
278 #define makeCall(n, argstypedecl, argstype, argsdecl, argsues, comma) \
279 template <typename R comma argstypedecl> \
280 void* makeCall(boost::function<R(argstype)> f, void** args) \
282 BOOST_PP_REPEAT(n, declType, _) detail::AnyReferenceCopy val; \
283 val(), f(BOOST_PP_REPEAT(n, callArgBF, _)); \
284 return val.rawValue(); \
289 #define makeCall(n, argstypedecl, argstype, argsdecl, argsues, comma) \
290 template <typename R comma argstypedecl> \
291 void* makeCall(R (Class::*f)(argstype), void* instance, void** args) \
293 detail::AnyReferenceCopy val; \
294 Class* cptr = *(Class**)instance; \
295 val(), ((*cptr).*f)(BOOST_PP_REPEAT(n, callArg, _)); \
296 return val.rawValue(); \
301 #define makeCall_(n, argstypedecl, argstype, argsdecl, argsues, comma) \
302 template <typename R comma argstypedecl> \
303 void* makeCall(R (Class::*f)(argstype), void** args) \
305 return makeCall(f, args[0], args + 1); \
312 #ifdef QITYPE_TRACK_FUNCTIONTYPE_INSTANCES
314 void QI_API functionTypeTrack(
const std::string& functionName);
315 void QI_API functionTypeDump();
326 if (size() != b.size())
327 return size() < b.size();
328 for (
unsigned i=0; i<size(); ++i)
330 if ( (*
this)[i]->info() != b[i]->info())
331 return (*
this)[i]->info() < b[i]->info();
347 template<
typename T,
typename S>
351 typedef typename boost::function_types::result_type<T>::type
ReturnType;
355 #ifdef QITYPE_TRACK_FUNCTIONTYPE_INSTANCES
356 detail::functionTypeTrack(
typeid(S).name());
359 virtual void*
call(
void* storage,
void** args,
unsigned int argc)
361 #if QI_HAS_VARIABLE_LENGTH_ARRAY
369 out =
new void*[argc];
375 if (boost::is_pointer<ReturnType>::value
387 #if ! QI_HAS_VARIABLE_LENGTH_ARRAY
397 std::vector<TypeInterface*> key(argsType);
398 key.push_back(returnType);
399 typedef std::map<InfosKeyMask, FunctionTypeInterfaceEq<T, S>* > FTMap;
400 static FTMap* ftMap = 0;
401 static boost::mutex* mutex = 0;
403 boost::mutex::scoped_lock lock(*mutex);
429 if (boost::is_reference<T>::value && !boost::is_const<
430 typename boost::remove_reference<T>::type>::value)
431 qiLogWarning() <<
"Function argument is a non-const reference: " <<
typeid(T).name();
452 typename boost::remove_const<
453 typename boost::remove_reference<T>::type
455 target->push_back(result);
463 typedef typename boost::function_types::member_function_pointer<F>::type
type;
467 typedef typename boost::function_types::function_pointer<F>::type
type;
473 typedef typename boost::function_types::parameter_types<F>::type ArgsType;
474 typedef typename boost::function_types::result_type<F>::type ResType;
476 std::vector<TypeInterface*> argumentsType;
478 boost::mpl::for_each<
479 boost::mpl::transform_view<ArgsType,
485 typedef typename boost::function_types::components<MapedF>::type EqComponents;
488 boost::is_member_function_pointer<F>::value>::type EqFunPtr;
496 template<
typename C,
typename R>
503 nargs.
args().resize(vargs.size()-1);
504 for (
unsigned i=0; i<vargs.size()-1; ++i)
505 nargs.
args()[i] = vargs[i+1];
506 C* inst = (C*)vargs.front().rawValue();
508 qiLogWarning(
"qitype.AnyArgumentsBouncer") <<
"Null instance";
510 output(), (*inst.*fun)(nargs);
523 nargs.
args().resize(vargs.size());
524 for (
unsigned i=0; i<vargs.size(); ++i)
525 nargs.
args()[i] = vargs[i];
533 template<
typename C,
typename R>
545 boost::function<R (const AnyArguments&)> fu = fun;
565 typedef typename boost::function_types::parameter_types<F>::type ArgsType;
566 typedef typename boost::function_types::result_type<F>::type ResType;
568 std::vector<TypeInterface*> argumentsType;
569 boost::mpl::for_each<
570 boost::mpl::transform_view<ArgsType,
575 return AnyFunction(ftype,
new boost::function<F>(func));
579 template<
typename T>
struct AnyFunctionMaker
586 template<
typename T>
struct AnyFunctionMaker<T*>
588 static AnyFunction make(T* func)
593 template<
typename R,
typename F,
typename B>
594 struct AnyFunctionMaker<boost::_bi::bind_t<R, F, B> >
596 static AnyFunction make(boost::_bi::bind_t<R, F, B> v)
598 typedef typename boost::function<
typename boost_bind_function_type<
599 boost::_bi::bind_t<R, F, B> >::type> CompatType;
604 template<
typename T>
struct AnyFunctionMaker<boost::function<T> >
606 static AnyFunction make(boost::function<T> func)
608 assert(
sizeof(boost::function<T>) ==
sizeof(boost::function<
void ()>));
613 template<
typename T>
struct AnyFunctionMaker<const T&>
614 :
public AnyFunctionMaker<T> {};
615 template<>
struct AnyFunctionMaker<AnyFunction>
617 static AnyFunction make(AnyFunction func)
627 return detail::AnyFunctionMaker<T>::make(f);
648 template<
typename F,
typename C>
654 typedef typename boost::function_types::result_type<F>::type Result;
655 typedef typename boost::function_types::parameter_types<F, boost::mpl::identity<boost::mpl::_1> >::type Args;
656 typedef typename boost::mpl::pop_front<Args>::type ArgsNoClass;
657 typedef typename boost::mpl::push_front<ArgsNoClass, detail::Class&>::type ArgsFakeClass;
658 typedef typename boost::mpl::push_front<ArgsFakeClass, Result>::type ComponentsFaked;
659 typedef typename boost::function_types::member_function_pointer<ComponentsFaked>::type MethodTypeFaked;
660 MethodTypeFaked newFunk = *(MethodTypeFaked*)(
void*)&func;
664 typedef typename boost::mpl::at_c<Args, 0>::type FirstArg;
667 if (!ptr && instance)
668 throw std::runtime_error(
"makeAnyFunction: failed to dynamic_cast bound value to expected type");
674 #endif // _QITYPE_DETAILS_ANYFUNCTIONFACTORY_HXX_
void transformRef(void **args, void **out, unsigned int sz, unsigned long refMask)
static const unsigned long refMask
virtual void * ptrFromStorage(void **)=0
virtual void * call(void *storage, void **args, unsigned int argc)
#define makeCall_(n, argstypedecl, argstype, argsdecl, argsues, comma)
boost::false_type isReference
static AnyFunction from(F func)
bool operator<(const InfosKeyMask &b) const
FunctionTypeInterfaceEq(unsigned long refMask)
#define qiLogCategory(Cat)
boost::function< RF > bind(const AF &fun,...)
boost::function_types::function_pointer< F >::type type
AnyFunction makeAnyFunctionBare(F func)
boost::mpl::push_front< EqArguments, detail::Class & >::type EqComponentsInt
boost::true_type isReference
boost::mpl::pop_front< MethodArguments >::type Arguments
void operator()(Ident< T >)
FunctionTypeInterface * functionType() const
#define QI_THREADSAFE_NEW(...)
Safe static initialization of variables.
boost::mpl::transform< Arguments, EqType< boost::mpl::_1 > >::type EqArguments
boost::function_types::function_type< EqComponents >::type type
_QI_BOUNCE_TYPE_METHODS(DefaultTypeImplMethods< S >)
#define qiLogWarning(...)
Log in warning mode.
boost::is_reference< T >::type isReference
fill_arguments(std::vector< TypeInterface * > *target)
boost::function_types::member_function_pointer< EqComponents >::type type
#define makeCall(n, argstypedecl, argstype, argsdecl, argsues, comma)
const std::vector< TypeInterface * > & argumentsType()
AnyReference bouncer(const AnyReferenceVector &vargs, R(C::*fun)(const AnyArguments &))
A function with AnyArguments as its sole argument will behave as if AnyFunction::fromDynamicFunction ...
boost::function_types::parameter_types< F >::type MethodArguments
boost::is_reference< T >::type isReference
std::vector< AnyReference > AnyReferenceVector
boost::function_types::result_type< T >::type ReturnType
boost::function_types::components< F >::type Components
boost::mpl::transform< Arguments, EqType< boost::mpl::_1 > >::type EqArguments
void operator()(T *) const
boost::true_type isReference
boost::mpl::if_< typename boost::is_fundamental< T >::type, void *, T >::type type
static T * pointer(T *&t)
boost::false_type isReference
boost::true_type isReference
boost::mpl::if_< typename boost::is_fundamental< T >::type, void *, T >::type rType
const AnyFunction & prependArgument(void *value) const
Prepend extra argument value to argument list.
TypeInterface * _resultType
boost::function_types::parameter_types< F >::type Arguments
static AnyFunction fromDynamicFunction(DynamicFunction f)
static const unsigned long refMask
boost::function_types::components< F >::type Components
boost::mpl::push_front< EqComponentsInt, EqResult >::type EqComponents
boost::function_types::member_function_pointer< F >::type type
AnyReference clone() const
void operator,(AnyReferenceCopy &g, const T &any)
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)
AnyReferenceCopy & operator()()
boost::false_type isReference
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.
EqType< Result >::rType EqResult
boost::false_type isReference
std::vector< TypeInterface * > _argumentsType
InfosKeyMask(const std::vector< TypeInterface * > &b, unsigned long mask)
boost::mpl::push_front< EqArguments, EqResult >::type EqComponents
boost::function_types::result_type< F >::type Result
EqType< Result >::rType EqResult
boost::function_types::result_type< F >::type Result
std::vector< TypeInterface * > * target
virtual void * initializeStorage(void *ptr=0)=0