X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;ds=sidebyside;f=libs%2Fgeneric%2Fcallback.h;h=577dd9d958bd337082f9c2479c5c1803e664c1a3;hb=8b9d70187635fa285e2877214cca70e12dfcfd98;hp=ef74e0cc90d068411c15f3e1ae106dba754cbf18;hpb=3df6d45c403dbfbb0c772e8fc7a661a52c1d3244;p=xonotic%2Fnetradiant.git diff --git a/libs/generic/callback.h b/libs/generic/callback.h index ef74e0cc..577dd9d9 100644 --- a/libs/generic/callback.h +++ b/libs/generic/callback.h @@ -27,392 +27,323 @@ #include #include "functional.h" -#include "callbackfwd.h" -template -inline void* convertToOpaque( Type* t ){ - return t; -} -template -inline void* convertToOpaque( const Type* t ){ - return const_cast( t ); -} -template -inline void* convertToOpaque( Type& t ){ - return &t; -} -template -inline void* convertToOpaque( const Type& t ){ - return const_cast( &t ); -} +namespace detail { + template + class CallbackBase { + void *m_environment; + Thunk_ m_thunk; + public: + typedef Thunk_ Thunk; -template -class ConvertFromOpaque -{ -}; + CallbackBase(void *environment, Thunk function) : m_environment(environment), m_thunk(function) { + } -template -class ConvertFromOpaque -{ -public: -static Type& apply( void* p ){ - return *static_cast( p ); -} -}; + void *getEnvironment() const { + return m_environment; + } -template -class ConvertFromOpaque -{ -public: -static const Type& apply( void* p ){ - return *static_cast( p ); -} -}; + Thunk getThunk() const { + return m_thunk; + } + }; + template + inline bool operator==(const CallbackBase &self, const CallbackBase &other) { + return self.getEnvironment() == other.getEnvironment() && self.getThunk() == other.getThunk(); + } -template -class ConvertFromOpaque -{ -public: -static Type* apply( void* p ){ - return static_cast( p ); -} -}; + template + inline bool operator!=(const CallbackBase &self, const CallbackBase &other) { + return !(self == other); + } -template -class ConvertFromOpaque -{ -public: -static const Type* apply( void* p ){ - return static_cast( p ); -} -}; + template + inline bool operator<(const CallbackBase &self, const CallbackBase &other) { + return self.getEnvironment() < other.getEnvironment() || + (!(other.getEnvironment() < self.getEnvironment()) && self.getThunk() < other.getThunk()); + } -template -class CallbackBase -{ -void* m_environment; -Thunk_ m_thunk; -public: -typedef Thunk_ Thunk; -CallbackBase( void* environment, Thunk function ) : m_environment( environment ), m_thunk( function ){ -} -void* getEnvironment() const { - return m_environment; } -Thunk getThunk() const { - return m_thunk; -} -}; -template -inline bool operator==( const CallbackBase& self, const CallbackBase& other ){ - return self.getEnvironment() == other.getEnvironment() && self.getThunk() == other.getThunk(); -} -template -inline bool operator!=( const CallbackBase& self, const CallbackBase& other ){ - return !( self == other ); -} -template -inline bool operator<( const CallbackBase& self, const CallbackBase& other ){ - return self.getEnvironment() < other.getEnvironment() || - ( !( other.getEnvironment() < self.getEnvironment() ) && self.getThunk() < other.getThunk() ); -} +namespace detail { -template -class BindFirstOpaqueN; + template + struct ConvertFromOpaque { + }; -template -class BindFirstOpaqueN { - FirstBound firstBound; -public: - explicit BindFirstOpaqueN(FirstBound firstBound) : firstBound(firstBound) { - } + // reference - R operator()(Ts... args) const { - return Caller::call(firstBound, args...); + template + inline const void *convertToOpaque(const T &t) { + return &t; } - FirstBound getBound() const { - return firstBound; - } + template + struct ConvertFromOpaque { + static T const &apply(void *p) { + return *static_cast(p); + } + }; - static R thunk(void *environment, Ts... args) { - return Caller::call(ConvertFromOpaque::apply(environment), args...); + template + inline void *convertToOpaque(T &t) { + return &t; } - void *getEnvironment() const { - return convertToOpaque(firstBound); - } -}; + template + struct ConvertFromOpaque { + static T &apply(void *p) { + return *static_cast( p ); + } + }; -template -using BindFirstOpaque = BindFirstOpaqueN; + // pointer -template -class CallbackN; + template + inline const void *convertToOpaque(const T *t) { + return t; + } -template -class CallbackN : public CallbackBase { - using Base = CallbackBase; + template + struct ConvertFromOpaque { + static const T *apply(void *p) { + return static_cast(p); + } + }; - static R nullThunk(void *, Ts...) { + template + inline void *convertToOpaque(T *t) { + return t; } -public: - using func = R(Ts...); + template + struct ConvertFromOpaque { + static T *apply(void *p) { + return static_cast(p); + } + }; - CallbackN() : Base(0, nullThunk) { - } + // function pointer - template - CallbackN(const BindFirstOpaque &caller) : Base(caller.getEnvironment(), BindFirstOpaque::thunk) { + template + inline const void *convertToOpaque(R(*const &t)(Ts...)) { + return &t; } - CallbackN(void *environment, typename Base::Thunk function) : Base(environment, function) { - } + template + struct ConvertFromOpaque { + using Type = R(*)(Ts...); - R operator()(Ts... args) const { - return Base::getThunk()(Base::getEnvironment(), args...); - } -}; + static Type const &apply(void *p) { + return *static_cast(p); + } + }; -/// \brief Combines a void pointer with a pointer to a function which operates on a void pointer. -/// -/// Use with the callback constructors MemberCaller, ConstMemberCaller, ReferenceCaller, ConstReferenceCaller, PointerCaller, ConstPointerCaller and FreeCaller. -template -class Callback0 : public CallbackN { -public: - using CallbackN::CallbackN; -}; + template + inline void *convertToOpaque(R(*&t)(Ts...)) { + return &t; + } -template -inline Callback0> makeCallback0(const Caller &caller, get_argument callee) { - return Callback0>(BindFirstOpaque(callee)); -} -template -inline Callback0> makeStatelessCallback0(const Caller &caller) { - return makeCallback0( Caller0To1(), 0 ); -} + template + struct ConvertFromOpaque { + using Type = R(*)(Ts...); -typedef Callback0 Callback; + static Type &apply(void *p) { + return *static_cast(p); + } + }; + template + class BindFirstOpaqueN; + template + class BindFirstOpaqueN { + FirstBound firstBound; + public: + explicit BindFirstOpaqueN(FirstBound firstBound) : firstBound(firstBound) { + } -/// \brief Combines a void pointer with a pointer to a function which operates on a void pointer and one other argument. -/// -/// Use with the callback constructors MemberCaller1, ConstMemberCaller1, ReferenceCaller1, ConstReferenceCaller1, PointerCaller1, ConstPointerCaller1 and FreeCaller1. -template -class Callback1 : public CallbackN { -public: - using CallbackN::CallbackN; -}; + R operator()(Ts... args) const { + return Caller::call(firstBound, args...); + } -template -inline Callback1, get_result_type> -makeCallback1(const Caller &caller, get_argument callee) { - return Callback1, get_result_type>(BindFirstOpaque(callee)); -} -template -inline Callback1, get_result_type> makeStatelessCallback1(const Caller &caller) { - return makeCallback1( Caller1To2(), 0 ); -} + FirstBound getBound() const { + return firstBound; + } + static R thunk(void *environment, Ts... args) { + return thunk_(detail::ConvertFromOpaque::apply(environment), args...); + } -/// \brief Combines a void pointer with a pointer to a function which operates on a void pointer and two other arguments. -/// -template -class Callback2 : public CallbackN { -public: - using CallbackN::CallbackN; -}; + static R thunk_(FirstBound environment, Ts... args) { + return Caller::call(environment, args...); + } + + void *getEnvironment() const { + return const_cast(detail::convertToOpaque(firstBound)); + } + }; -template -inline Callback2< - get_argument, - get_argument, - get_result_type -> makeCallback2(const Caller &caller, get_argument callee) { - return Callback2< - get_argument, - get_argument, - get_result_type - >(BindFirstOpaque(callee)); -} -template -inline Callback2< - get_argument, - get_argument, - get_result_type -> makeStatelessCallback2(const Caller &caller) { - return makeCallback2( Caller2To3(), 0 ); } +template +using BindFirstOpaque = detail::BindFirstOpaqueN>; -/// \brief Combines a void pointer with a pointer to a function which operates on a void pointer and three other arguments. +/// \brief Combines a void pointer with a pointer to a function which operates on a void pointer. /// -template -class Callback3 : public CallbackN { +/// Use with the callback constructors MemberCaller0, ConstMemberCaller0, ReferenceCaller0, ConstReferenceCaller0, PointerCaller0, ConstPointerCaller0 and FreeCaller0. +template +class Callback; + +template +class Callback : public detail::CallbackBase { + using Base = detail::CallbackBase; + + static R nullThunk(void *, Ts...) { + } + public: - using CallbackN::CallbackN; -}; + using func = R(Ts...); -template -inline Callback3< - get_argument, - get_argument, - get_argument, - get_result_type -> makeCallback3(const Caller &caller, get_argument callee) { - return Callback3< - get_argument, - get_argument, - get_argument, - get_result_type - >(BindFirstOpaque(callee)); -} -template -inline Callback3< - get_argument, - get_argument, - get_argument, - get_result_type -> makeStatelessCallback3(const Caller &caller) { - return makeCallback3( Caller3To4(), 0 ); -} + Callback() : Base(0, nullThunk) { + } + template + Callback(const BindFirstOpaque &caller) : Base(caller.getEnvironment(), BindFirstOpaque::thunk) { + } -/// \brief Forms a Callback from a non-const Environment reference and a non-const Environment member-function. -/// -/// \dontinclude generic/callback.cpp -/// \skipline MemberCaller example -/// \until end example -template -using MemberCaller = BindFirstOpaque>; + Callback(void *environment, typename Base::Thunk function) : Base(environment, function) { + } -/// \brief Forms a Callback from a const Environment reference and a const Environment member-function. -/// -/// \dontinclude generic/callback.cpp -/// \skipline MemberCaller example -/// \until end example -template -using ConstMemberCaller = BindFirstOpaque>; + R operator()(Ts... args) const { + return Base::getThunk()(Base::getEnvironment(), args...); + } +}; -/// \brief Forms a Callback from a non-const Environment reference and a const Environment member-function which takes one argument. -template -using MemberCaller1 = BindFirstOpaque>; +namespace detail { + template + struct Arglist; -/// \brief Forms a Callback from a const Environment reference and a const Environment member-function which takes one argument. -template -using ConstMemberCaller1 = BindFirstOpaque>; + template + struct Arglist { + using type = R(Head, Ts...); -/// \brief Forms a Callback from a non-const Environment reference and a free function which operates on a non-const Environment reference. -/// -/// \dontinclude generic/callback.cpp -/// \skipline ReferenceCaller example -/// \until end example -template -using ReferenceCaller = BindFirstOpaque>; + template + using unshift = Arglist; -/// \brief Forms a Callback from a const Environment reference and a free function which operates on a const Environment reference. -/// -/// \dontinclude generic/callback.cpp -/// \skipline ReferenceCaller example -/// \until end example -template -using ConstReferenceCaller = BindFirstOpaque>; + using shift = Arglist; + }; -/// \brief Forms a Callback from a non-const Environment reference and a free function which operates on a non-const Environment reference and one other argument. -template -using ReferenceCaller1 = BindFirstOpaque>; + template + struct Arglist { + using type = R(Ts...); -/// \brief Forms a Callback from a const Environment reference and a free function which operates on a const Environment reference and one other argument. -template -using ConstReferenceCaller1 = BindFirstOpaque>; + template + using unshift = Arglist; + }; -/// \brief Forms a Callback from a non-const Environment pointer and a free function which operates on a non-const Environment pointer. -template -using PointerCaller = BindFirstOpaque>; + template + using ArgShift = typename detail::Arglist::shift::type; -/// \brief Forms a Callback from a const Environment pointer and a free function which operates on a const Environment pointer. -template -using ConstPointerCaller = BindFirstOpaque>; + template + using ArgUnshift = typename detail::Arglist::template unshift::type; +} -/// \brief Forms a Callback from a non-const Environment pointer and a free function which operates on a non-const Environment pointer and one other argument. -template -using PointerCaller1 = BindFirstOpaque>; +template +inline Callback>> makeCallback(const Caller &caller, get_argument callee) { + return BindFirstOpaque(callee); +} -/// \brief Forms a Callback from a const Environment pointer and a free function which operates on a const Environment pointer and one other argument. -template -using ConstPointerCaller1 = BindFirstOpaque>; +template +class CallerShiftFirst; -/// \brief Forms a Callback from a free function which takes no arguments. -template -class FreeCaller : public BindFirstOpaque>> { +template +class CallerShiftFirst { public: - FreeCaller() : BindFirstOpaque>>(0) { - } -}; + using func = R(FirstArgument, Ts...); -/// \brief Forms a Callback from a free function which takes a single argument. -template -class FreeCaller1 : public BindFirstOpaque>> { -public: - FreeCaller1() : BindFirstOpaque>>(0) { + static R call(FirstArgument, Ts... args) { + return Caller::call(args...); } }; - -/// \brief Constructs a Callback from a non-const \p functor with zero arguments. -/// -/// \param Functor Must define \c operator()(). -template -inline Callback makeCallback( Functor& functor ){ - return Callback( MemberCaller( functor ) ); +template +inline Callback> makeStatelessCallback(const Caller &caller) { + return makeCallback(CallerShiftFirst, void *>>(), nullptr); } -/// \brief Constructs a Callback from a const \p functor with zero arguments. -/// -/// \param Functor Must define const \c operator()(). -template -inline Callback makeCallback( const Functor& functor ){ - return Callback( ConstMemberCaller( functor ) ); -} +/// \brief Forms a Callback from a non-const Environment reference and a non-const Environment member-function. +template member> +using MemberCaller = BindFirstOpaque>; -/// \brief Constructs a Callback1 from a non-const \p functor with one argument. +/// \brief Constructs a Callback1 from a non-const \p functor /// /// \param Functor Must define \c first_argument_type and \c operator()(first_argument_type). template -inline Callback1> makeCallback1(Functor &functor) { - typedef get_argument FirstArgument; - return Callback1( MemberCaller1( functor ) ); +inline Callback> makeCallback(Functor &functor) { + return MemberCaller, &Functor::operator()>(functor); } -/// \brief Constructs a Callback1 from a const \p functor with one argument. +/// \brief Forms a Callback from a const Environment reference and a const Environment member-function. +template member> +using ConstMemberCaller = BindFirstOpaque>; + +/// \brief Constructs a Callback1 from a const \p functor /// /// \param Functor Must define \c first_argument_type and const \c operator()(first_argument_type). template -inline Callback1> makeCallback1(const Functor &functor) { - typedef get_argument FirstArgument; - return Callback1( ConstMemberCaller1( functor ) ); +inline Callback> makeCallback(const Functor &functor) { + return ConstMemberCaller, &Functor::operator()>(functor); } +/// \brief Forms a Callback from a non-const Environment reference and a free function which operates on a non-const Environment reference. +template *func> +using ReferenceCaller = BindFirstOpaque, func>>; -typedef Callback1 BoolImportCallback; -typedef Callback1 BoolExportCallback; - -typedef Callback1 IntImportCallback; -typedef Callback1 IntExportCallback; +/// \brief Forms a Callback from a const Environment reference and a free function which operates on a const Environment reference. +template *func> +using ConstReferenceCaller = BindFirstOpaque, func>>; -typedef Callback1 FloatImportCallback; -typedef Callback1 FloatExportCallback; +/// \brief Forms a Callback from a non-const Environment pointer and a free function which operates on a non-const Environment pointer. +template *func> +using PointerCaller = BindFirstOpaque, func>>; -typedef Callback1 StringImportCallback; -typedef Callback1 StringExportCallback; +/// \brief Forms a Callback from a const Environment pointer and a free function which operates on a const Environment pointer. +template *func> +using ConstPointerCaller = BindFirstOpaque, func>>; + +namespace detail { + template + class FreeCaller : public BindFirstOpaque>> { + public: + FreeCaller() : BindFirstOpaque>>(nullptr) { + } + }; + + template + struct FreeCallerWrapper; + + template + struct FreeCallerWrapper { + using func = R(void *, Ts...); + + static R call(void *f, Ts... args) { + // ideally, we'd get the implementation of the function type directly. Instead, it's passed in + return reinterpret_cast(f)(args...); + } + }; +} -typedef Callback1 SizeImportCallback; -typedef Callback1 SizeExportCallback; +/// \brief Forms a Callback from a free function +template +using FreeCaller = detail::FreeCaller, F>; +template +inline Callback makeCallbackF(R(*func)(Ts...)) { + void *pVoid = reinterpret_cast(func); + return BindFirstOpaque>(pVoid); +} #endif