#if !defined( INCLUDED_GENERIC_CLOSURE_H ) #define INCLUDED_GENERIC_CLOSURE_H /// \file /// \brief Type-safe techniques for binding the first argument of an anonymous callback. #include /// \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. class Callback { typedef void ( *Thunk )( void* ); void* m_environment; Thunk m_thunk; static void nullThunk( void* ){ } public: Callback() : m_environment( 0 ), m_thunk( nullThunk ){ } Callback( void* environment, Thunk function ) : m_environment( environment ), m_thunk( function ){ } void* getEnvironment() const { return m_environment; } Thunk getThunk() const { return m_thunk; } void operator()() const { m_thunk( m_environment ); } }; inline bool operator==( const Callback& self, const Callback& other ){ return self.getEnvironment() == other.getEnvironment() && self.getThunk() == other.getThunk(); } inline bool operator<( const Callback& self, const Callback& other ){ return self.getEnvironment() < other.getEnvironment() || ( !( other.getEnvironment() < self.getEnvironment() ) && self.getThunk() < other.getThunk() ); } /// \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 { typedef void ( *Thunk )( void*, FirstArgument ); void* m_environment; Thunk m_thunk; static void nullThunk( void*, FirstArgument ){ } public: typedef FirstArgument first_argument_type; Callback1() : m_environment( 0 ), m_thunk( nullThunk ){ } Callback1( void* environment, Thunk function ) : m_environment( environment ), m_thunk( function ){ } void* getEnvironment() const { return m_environment; } Thunk getThunk() const { return m_thunk; } void operator()( FirstArgument firstArgument ) const { m_thunk( m_environment, firstArgument ); } }; template inline bool operator==( const Callback1& self, const Callback1& other ){ return self.getEnvironment() == other.getEnvironment() && self.getThunk() == other.getThunk(); } template inline bool operator<( const Callback1& self, const Callback1& other ){ return self.getEnvironment() < other.getEnvironment() || ( !( other.getEnvironment() < self.getEnvironment() ) && self.getThunk() < other.getThunk() ); } template class FunctorInvoke { public: inline void operator()( Functor functor ){ functor(); } }; typedef FunctorInvoke CallbackInvoke; template class Functor1Invoke { FirstArgument m_firstArgument; public: Functor1Invoke( FirstArgument firstArgument ) : m_firstArgument( firstArgument ){ } inline void operator()( Functor functor ){ functor( m_firstArgument ); } }; typedef Callback1 BoolImportCallback; typedef Callback1 BoolExportCallback; typedef Callback1 IntImportCallback; typedef Callback1 IntExportCallback; typedef Callback1 FloatImportCallback; typedef Callback1 FloatExportCallback; typedef Callback1 StringImportCallback; typedef Callback1 StringExportCallback; typedef Callback1 SizeImportCallback; typedef Callback1 SizeExportCallback; /// \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 class MemberCaller { Environment& m_environment; public: MemberCaller( Environment& environment ) : m_environment( environment ){ } void* getEnvironment() const { return &m_environment; } static void thunk( void* environment ){ ( ( *reinterpret_cast( environment ) ).*member )(); } operator Callback() const { return Callback( getEnvironment(), thunk ); } }; /// \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 class ConstMemberCaller { const Environment& m_environment; public: ConstMemberCaller( const Environment& environment ) : m_environment( environment ){ } void* getEnvironment() const { return const_cast( &m_environment ); } static void thunk( void* environment ){ ( ( *reinterpret_cast( environment ) ).*member )(); } operator Callback() const { return Callback( getEnvironment(), thunk ); } }; /// \brief Forms a Callback from a non-const Environment reference and a const Environment member-function which takes one argument. template class MemberCaller1 { Environment& m_environment; public: MemberCaller1( Environment& environment ) : m_environment( environment ){ } void* getEnvironment() const { return &m_environment; } static void thunk( void* environment, FirstArgument firstArgument ){ ( ( *reinterpret_cast( environment ) ).*member )( firstArgument ); } operator Callback1( ) const { return Callback1( getEnvironment(), thunk ); } }; /// \brief Forms a Callback from a const Environment reference and a const Environment member-function which takes one argument. template class ConstMemberCaller1 { const Environment& m_environment; public: ConstMemberCaller1( const Environment& environment ) : m_environment( environment ){ } void* getEnvironment() const { return const_cast( &m_environment ); } static void thunk( void* environment, FirstArgument firstArgument ){ ( ( *reinterpret_cast( environment ) ).*member )( firstArgument ); } operator Callback1( ) const { return Callback1( getEnvironment(), thunk ); } }; /// \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 class ReferenceCaller { Environment& m_environment; public: ReferenceCaller( Environment& environment ) : m_environment( environment ){ } void* getEnvironment() const { return &m_environment; } static void thunk( void* environment ){ (func)( *reinterpret_cast( environment ) ); } operator Callback() const { return Callback( getEnvironment(), thunk ); } }; /// \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 class ConstReferenceCaller { const Environment& m_environment; public: ConstReferenceCaller( const Environment& environment ) : m_environment( environment ){ } void* getEnvironment() const { return const_cast( &m_environment ); } static void thunk( void* environment ){ (func)( *reinterpret_cast( environment ) ); } operator Callback() const { return Callback( getEnvironment(), thunk ); } }; /// \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 class ReferenceCaller1 { Environment& m_environment; public: ReferenceCaller1( Environment& environment ) : m_environment( environment ){ } void* getEnvironment() const { return &m_environment; } static void thunk( void* environment, FirstArgument firstArgument ){ (func)( *reinterpret_cast( environment ), firstArgument ); } operator Callback1( ) const { return Callback1( getEnvironment(), thunk ); } }; /// \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 class ConstReferenceCaller1 { const Environment& m_environment; public: ConstReferenceCaller1( const Environment& environment ) : m_environment( environment ){ } void* getEnvironment() const { return const_cast( &m_environment ); } static void thunk( void* environment, FirstArgument firstArgument ){ (func)( *reinterpret_cast( environment ), firstArgument ); } operator Callback1( ) const { return Callback1( getEnvironment(), thunk ); } }; /// \brief Forms a Callback from a non-const Environment pointer and a free function which operates on a non-const Environment pointer. template class PointerCaller { Environment* m_environment; public: PointerCaller( Environment* environment ) : m_environment( environment ){ } void* getEnvironment() const { return m_environment; } static void thunk( void* environment ){ (func)( reinterpret_cast( environment ) ); } operator Callback() const { return Callback( getEnvironment(), thunk ); } }; /// \brief Forms a Callback from a const Environment pointer and a free function which operates on a const Environment pointer. template class ConstPointerCaller { const Environment* m_environment; public: ConstPointerCaller( const Environment* environment ) : m_environment( environment ){ } void* getEnvironment() const { return const_cast( m_environment ); } static void thunk( void* environment ){ (func)( reinterpret_cast( environment ) ); } operator Callback() const { return Callback( getEnvironment(), thunk ); } }; /// \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 class PointerCaller1 { Environment* m_environment; public: PointerCaller1( Environment* environment ) : m_environment( environment ){ } void* getEnvironment() const { return m_environment; } static void thunk( void* environment, FirstArgument firstArgument ){ (func)( reinterpret_cast( environment ), firstArgument ); } operator Callback1( ) const { return Callback1( getEnvironment(), thunk ); } }; /// \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 class ConstPointerCaller1 { const Environment* m_environment; public: ConstPointerCaller1( const Environment* environment ) : m_environment( environment ){ } void* getEnvironment() const { return const_cast( m_environment ); } static void thunk( void* environment, FirstArgument firstArgument ){ (func)( reinterpret_cast( environment ), firstArgument ); } operator Callback1( ) const { return Callback1( getEnvironment(), thunk ); } }; /// \brief Forms a Callback from a free function which takes no arguments. template class FreeCaller { public: void* getEnvironment() const { return 0; } static void thunk( void* ){ (func)( ); } operator Callback() const { return Callback( getEnvironment(), thunk ); } }; /// \brief Forms a Callback from a free function which takes a single argument. template class FreeCaller1 { public: void* getEnvironment() const { return 0; } static void thunk( void*, FirstArgument firstArgument ){ (func)( firstArgument ); } operator Callback1( ) const { return Callback1( getEnvironment(), thunk ); } }; /// \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 ) ); } /// \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 Constructs a Callback1 from a non-const \p functor with one argument. /// /// \param Functor Must define \c first_argument_type and \c operator()(first_argument_type). template inline Callback1 makeCallback1( Functor& functor ){ typedef typename Functor::first_argument_type FirstArgument; return Callback1( MemberCaller1( functor ) ); } /// \brief Constructs a Callback1 from a const \p functor with one argument. /// /// \param Functor Must define \c first_argument_type and const \c operator()(first_argument_type). template inline Callback1 makeCallback1( const Functor& functor ){ typedef typename Functor::first_argument_type FirstArgument; return Callback1( ConstMemberCaller1( functor ) ); } #endif