Re: Casting PointerToMemeberFunction
mzaytsev2@bloomberg.net wrote:
I'm looking for the fastest way to dispatch events to member
functions.
I come up to solution like that:
class Binder {
public:
struct P {};
template < class T >
Binder( T* obj, void (T::*fptr)() )
: m_obj( reinterpret_cast< P* >( obj ) )
, m_fptr( static_cast< void (P::*)() >( fptr )
{}
void operator() () { ( m_obj->*m_fptr ) (); }
private:
P* m_obj;
void (P::*m_fptr)();
};
"If a nonstatic member function of a class X is called for an object
that is not of type X, or of a type derived from X, the behavior is
undefined." (9.3.1/1)
Just one thing up front: why not use one of the existing libraries for that,
like libSigC++ or Boost.Signal/Boost.Function?
class Handler : public Binder::P
{
public:
void foo();
};
Okay, you are deriving the target from a helper type in the binder. Now, why
would you do that and then use reinterpret_cast to get a pointer to that
baseclass? This will fail to produce the results you want when you have
multiple baseclasses, i.e. when the address of the Handler object is
different than the address of the Binder::P object.
Just for your info and inspiration, libSigC++1 does a similar thing, but it
does two things differently. Firstly, there is no template-constructor but
a factory function:
template<typename T>
functor bind( T* obj, void (T::*mfn)());
It then goes on to store the pointer to the object and the memberfunction in
typeless pointers (members of class functor):
functor tmp;
tmp.obj = make_typeless_object(obj);
tmp.function = make_typeless_function(mfn);
and an additional pointer to a (template-)function that first undoes the
conversions and then invokes the original:
tmp.proxy = &unpack_and_call<T>;
This function is defined as
template<typename T>
void unpack_and_call( obj_ptr o, fn_ptr f) {
// undo conversion
T* obj = make_object<T>(o);
void (T::*mfn)() = make_function<T>(f);
// invoke function
obj->(*mfn)();
}
Now, the problematic part is the type of the typeless storage for the
functor and the conversions. In libSigC++1, this uses a dummy type for the
object pointer (a locally defined class) and a matching memberfunction
pointer type. The latter is a problem though, because some pointers to
memberfunction have different sizes than just a mere object pointer. IIRC,
their size goes up to four pointers, and those are cases where libSigC++1
simply fails.
Anyway, the basic principle should be clear, use a template to convert
anything to a typeless representation and another template function to
convert it back.
HTH
Uli
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]