#pragma once /* callback.h * This is Rich Hickey's callback library... * http://www.tutok.sk/fastgl/callback.html * * I've just renamed it to callback.h as all my header files use * h for extension. */ //**************** callback.hpp ********************** // Copyright 1994 Rich Hickey /* Permission to use, copy, modify, distribute and sell this software * for any purpose is hereby granted without fee, * provided that the above copyright notice appear in all copies and * that both that copyright notice and this permission notice appear * in supporting documentation. Rich Hickey makes no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. */ // 06/12/94 Rich Hickey // 3rd major revision // Now functors are concrete classes, and should be held by value // Virtual function mechanism removed // Generic makeFunctor() mechanism added for building functors // from both stand-alone functions and object/ptr-to-mem-func pairs #ifndef CALLBACK_HPP #define CALLBACK_HPP /* To use: If you wish to build a component that provides/needs a callback, simply specify and hold a CBFunctor of the type corresponding to the args you wish to pass and the return value you need. There are 10 Functors from which to choose: CBFunctor0 CBFunctor1 CBFunctor2 CBFunctor3 CBFunctor4 CBFunctor0wRet CBFunctor1wRet CBFunctor2wRet CBFunctor3wRet CBFunctor4wRet These are parameterized by their args and return value if any. Each has a default ctor and an operator() with the corresponding signature. They can be treated and used just like ptr-to-functions. If you want to be a client of a component that uses callbacks, you create a CBFunctor by calling makeFunctor(). There are three flavors of makeFunctor - you can create a functor from: a ptr-to-stand-alone function an object and a pointer-to-member function. a pointer-to-member function (which will be called on first arg of functor) The current iteration of this library requires you pass makeFunctor() a dummy first argument of type ptr-to-the-Functor-type-you-want-to-create. Simply cast 0 to provide this argument: makeFunctor((target-functor*)0,ptr-to-function) makeFunctor((target-functor*)0,reference-to-object,ptr-to-member-function) makeFunctor((target-functor*)0,ptr-to-member-function) Future versions will drop this requirement once member templates are available. The functor system is 100% type safe. It is also type flexible. You can build a functor out of a function that is 'type compatible' with the target functor - it need not have an exactly matching signature. By type compatible I mean a function with the same number of arguments, of types reachable from the functor's argument types by implicit conversion. The return type of the function must be implicitly convertible to the return type of the functor. A functor with no return can be built from a function with a return - the return value is simply ignored. (See ethel example below) All the correct virtual function behavior is preserved. (see ricky example below). If you somehow try to create something in violation of the type system you will get a compile-time or template-instantiation- time error. The CBFunctor base class and translator classes are artifacts of this implementation. You should not write code that relies upon their existence. Nor should you rely on the return value of makeFunctor being anything in particular. All that is guaranteed is that the Functor classes have a default ctor, an operator() with the requested argument types and return type, an operator that will allow it to be evaluated in a conditional (with 'true' meaning the functor is set, 'false' meaning it is not), and that Functors can be constructed from the result of makeFunctor(), given you've passed something compatible to makeFunctor(). /////////////////////// BEGIN Example 1 ////////////////////////// #include #include "callback.hpp" //do5Times() is a function that takes a functor and invokes it 5 times void do5Times(const CBFunctor1 &doIt) { for(int i=0;i<5;i++) doIt(i); } //Here are some standalone functions void fred(int i){cout << "fred: " << i< *FtorType; CBFunctor1 ftor; //a functor variable //make a functor from ptr-to-function ftor = makeFunctor((FtorType)0,fred); do5Times(ftor); //note ethel is not an exact match - ok, is compatible ftor = makeFunctor((FtorType)0,ethel); do5Times(ftor); //create a D object to be a callback target D myD; //make functor from object and ptr-to-member-func ftor = makeFunctor((FtorType)0,myD,&B::ricky); do5Times(ftor); } /////////////////////// END of example 1 ////////////////////////// /////////////////////// BEGIN Example 2 ////////////////////////// #include #include "callback.hpp" //Button is a component that provides a functor-based //callback mechanism, so you can wire it up to whatever you wish class Button{ public: //ctor takes a functor and stores it away in a member Button(const CBFunctor0 &uponClickDoThis):notify(uponClickDoThis) {} void click() { //invoke the functor, thus calling back client notify(); } private: //note this is a data member with a verb for a name - matches its //function-like usage CBFunctor0 notify; }; class CDPlayer{ public: void play() {cout << "Playing"< //for memcpy #include //for size_t //typeless representation of a function and optional object class CBFunctorBase { public: typedef void (CBFunctorBase::* _MemFunc)(); typedef void (*_Func)(); CBFunctorBase() :callee(0), func(0) {} CBFunctorBase(const void* c, const void* f, size_t sz) { if (c) //must be callee/memfunc { callee = (void*)c; memcpy(memFunc, f, sz); } else //must be ptr-to-func { func = f; } } //for evaluation in conditionals operator int()const { return func || callee; } class DummyInit { }; //////////////////////////////////////////////////////////////// // Note: this code depends on all ptr-to-mem-funcs being same size // If that is not the case then make memFunc as large as largest //////////////////////////////////////////////////////////////// union { const void* func; char memFunc[sizeof(_MemFunc)]; }; void* callee; }; /************************* no arg - no return *******************/ class CBFunctor0 :protected CBFunctorBase { public: CBFunctor0(DummyInit* = 0) {} void operator()()const { thunk(*this); } CBFunctorBase::operator int; protected: typedef void (*Thunk)(const CBFunctorBase&); CBFunctor0(Thunk t, const void* c, const void* f, size_t sz) : CBFunctorBase(c, f, sz), thunk(t) {} private: Thunk thunk; }; template class CBMemberTranslator0 :public CBFunctor0 { public: CBMemberTranslator0(Callee& c, const MemFunc& m) : CBFunctor0(thunk, &c, &m, sizeof(MemFunc)) {} static void thunk(const CBFunctorBase& ftor) { Callee* callee = (Callee*)ftor.callee; MemFunc& memFunc(*(MemFunc*)(void*)(ftor.memFunc)); (callee->*memFunc)(); } }; template class CBFunctionTranslator0 :public CBFunctor0 { public: CBFunctionTranslator0(Func f) :CBFunctor0(thunk, 0, f, 0) {} static void thunk(const CBFunctorBase& ftor) { (Func(ftor.func))(); } }; template inline CBMemberTranslator0 makeFunctor(CBFunctor0*, Callee& c, TRT(CallType::* const& f)()) { typedef TRT(CallType::* MemFunc)(); return CBMemberTranslator0(c, f); } template inline CBMemberTranslator0 makeFunctor(CBFunctor0*, const Callee& c, TRT(CallType::* const& f)()const) { typedef TRT(CallType::* MemFunc)()const; return CBMemberTranslator0(c, f); } template inline CBFunctionTranslator0 makeFunctor(CBFunctor0*, TRT(*f)()) { return CBFunctionTranslator0(f); } /************************* no arg - with return *******************/ template class CBFunctor0wRet :protected CBFunctorBase { public: CBFunctor0wRet(DummyInit* = 0) {} RT operator()()const { return BC4_RET_BUG(thunk(*this)); } CBFunctorBase::operator int; protected: typedef RT(*Thunk)(const CBFunctorBase&); CBFunctor0wRet(Thunk t, const void* c, const void* f, size_t sz) : CBFunctorBase(c, f, sz), thunk(t) {} private: Thunk thunk; }; template class CBMemberTranslator0wRet :public CBFunctor0wRet { public: CBMemberTranslator0wRet(Callee& c, const MemFunc& m) : CBFunctor0wRet(thunk, &c, &m, sizeof(MemFunc)) {} static RT thunk(const CBFunctorBase& ftor) { Callee* callee = (Callee*)ftor.callee; MemFunc& memFunc(*(MemFunc*)(void*)(ftor.memFunc)); return BC4_RET_BUG((callee->*memFunc)()); } }; template class CBFunctionTranslator0wRet :public CBFunctor0wRet { public: CBFunctionTranslator0wRet(Func f) :CBFunctor0wRet(thunk, 0, f, 0) {} static RT thunk(const CBFunctorBase& ftor) { return (Func(ftor.func))(); } }; template inline CBMemberTranslator0wRet makeFunctor(CBFunctor0wRet*, Callee& c, TRT(CallType::* const& f)()) { typedef TRT(CallType::* MemFunc)(); return CBMemberTranslator0wRet(c, f); } template inline CBMemberTranslator0wRet makeFunctor(CBFunctor0wRet*, const Callee& c, TRT(CallType::* const& f)()const) { typedef TRT(CallType::* MemFunc)()const; return CBMemberTranslator0wRet(c, f); } template inline CBFunctionTranslator0wRet makeFunctor(CBFunctor0wRet*, TRT(*f)()) { return CBFunctionTranslator0wRet(f); } /************************* one arg - no return *******************/ template class CBFunctor1 :protected CBFunctorBase { public: CBFunctor1(DummyInit* = 0) {} void operator()(P1 p1)const { thunk(*this, p1); } CBFunctorBase::operator int; //for STL typedef P1 argument_type; typedef void result_type; protected: typedef void (*Thunk)(const CBFunctorBase&, P1); CBFunctor1(Thunk t, const void* c, const void* f, size_t sz) : CBFunctorBase(c, f, sz), thunk(t) {} private: Thunk thunk; }; template class CBMemberTranslator1 :public CBFunctor1 { public: CBMemberTranslator1(Callee& c, const MemFunc& m) : CBFunctor1(thunk, &c, &m, sizeof(MemFunc)) {} static void thunk(const CBFunctorBase& ftor, P1 p1) { Callee* callee = (Callee*)ftor.callee; MemFunc& memFunc(*(MemFunc*)(void*)(ftor.memFunc)); (callee->*memFunc)(p1); } }; template class CBFunctionTranslator1 :public CBFunctor1 { public: CBFunctionTranslator1(Func f) :CBFunctor1(thunk, 0, f, 0) {} static void thunk(const CBFunctorBase& ftor, P1 p1) { (Func(ftor.func))(p1); } }; template inline CBMemberTranslator1 makeFunctor(CBFunctor1*, Callee& c, TRT(CallType::* const& f)(TP1)) { typedef TRT(CallType::* MemFunc)(TP1); return CBMemberTranslator1(c, f); } template inline CBMemberTranslator1 makeFunctor(CBFunctor1*, const Callee& c, TRT(CallType::* const& f)(TP1)const) { typedef TRT(CallType::* MemFunc)(TP1)const; return CBMemberTranslator1(c, f); } template inline CBFunctionTranslator1 makeFunctor(CBFunctor1*, TRT(*f)(TP1)) { return CBFunctionTranslator1(f); } template class CBMemberOf1stArgTranslator1 :public CBFunctor1 { public: CBMemberOf1stArgTranslator1(const MemFunc& m) : CBFunctor1(thunk, (void*)1, &m, sizeof(MemFunc)) {} static void thunk(const CBFunctorBase& ftor, P1 p1) { MemFunc& memFunc(*(MemFunc*)(void*)(ftor.memFunc)); (p1.*memFunc)(); } }; template inline CBMemberOf1stArgTranslator1 makeFunctor(CBFunctor1*, TRT(CallType::* const& f)()) { typedef TRT(CallType::* MemFunc)(); return CBMemberOf1stArgTranslator1(f); } template inline CBMemberOf1stArgTranslator1 makeFunctor(CBFunctor1*, TRT(CallType::* const& f)()const) { typedef TRT(CallType::* MemFunc)()const; return CBMemberOf1stArgTranslator1(f); } /************************* one arg - with return *******************/ template class CBFunctor1wRet :protected CBFunctorBase { public: CBFunctor1wRet(DummyInit* = 0) {} RT operator()(P1 p1)const { return BC4_RET_BUG(thunk(*this, p1)); } CBFunctorBase::operator int; //for STL typedef P1 argument_type; typedef RT result_type; protected: typedef RT(*Thunk)(const CBFunctorBase&, P1); CBFunctor1wRet(Thunk t, const void* c, const void* f, size_t sz) : CBFunctorBase(c, f, sz), thunk(t) {} private: Thunk thunk; }; template class CBMemberTranslator1wRet :public CBFunctor1wRet { public: CBMemberTranslator1wRet(Callee& c, const MemFunc& m) : CBFunctor1wRet(thunk, &c, &m, sizeof(MemFunc)) {} static RT thunk(const CBFunctorBase& ftor, P1 p1) { Callee* callee = (Callee*)ftor.callee; MemFunc& memFunc(*(MemFunc*)(void*)(ftor.memFunc)); return BC4_RET_BUG((callee->*memFunc)(p1)); } }; template class CBFunctionTranslator1wRet :public CBFunctor1wRet { public: // CBFunctionTranslator1wRet(Func f):CBFunctor1wRet(thunk,0,f,0){} // EBR CBFunctionTranslator1wRet(Func f) :CBFunctor1wRet(thunk, 0, (void*)f, 0) {} static RT thunk(const CBFunctorBase& ftor, P1 p1) { return (Func(ftor.func))(p1); } }; template inline CBMemberTranslator1wRet makeFunctor(CBFunctor1wRet*, Callee& c, TRT(CallType::* const& f)(TP1)) { typedef TRT(CallType::* MemFunc)(TP1); return CBMemberTranslator1wRet(c, f); } template inline CBMemberTranslator1wRet makeFunctor(CBFunctor1wRet*, const Callee& c, TRT(CallType::* const& f)(TP1)const) { typedef TRT(CallType::* MemFunc)(TP1)const; return CBMemberTranslator1wRet(c, f); } template inline CBFunctionTranslator1wRet makeFunctor(CBFunctor1wRet*, TRT(*f)(TP1)) { return CBFunctionTranslator1wRet(f); } template class CBMemberOf1stArgTranslator1wRet :public CBFunctor1wRet { public: CBMemberOf1stArgTranslator1wRet(const MemFunc& m) : CBFunctor1wRet(thunk, (void*)1, &m, sizeof(MemFunc)) {} static RT thunk(const CBFunctorBase& ftor, P1 p1) { MemFunc& memFunc(*(MemFunc*)(void*)(ftor.memFunc)); return BC4_RET_BUG((p1.*memFunc)()); } }; template inline CBMemberOf1stArgTranslator1wRet makeFunctor(CBFunctor1wRet*, TRT(CallType::* const& f)()) { typedef TRT(CallType::* MemFunc)(); return CBMemberOf1stArgTranslator1wRet(f); } template inline CBMemberOf1stArgTranslator1wRet makeFunctor(CBFunctor1wRet*, TRT(CallType::* const& f)()const) { typedef TRT(CallType::* MemFunc)()const; return CBMemberOf1stArgTranslator1wRet(f); } /************************* two args - no return *******************/ template class CBFunctor2 :protected CBFunctorBase { public: CBFunctor2(DummyInit* = 0) {} void operator()(P1 p1, P2 p2)const { thunk(*this, p1, p2); } CBFunctorBase::operator int; //for STL typedef P1 first_argument_type; typedef P2 second_argument_type; typedef void result_type; protected: typedef void (*Thunk)(const CBFunctorBase&, P1, P2); CBFunctor2(Thunk t, const void* c, const void* f, size_t sz) : CBFunctorBase(c, f, sz), thunk(t) {} private: Thunk thunk; }; template class CBMemberTranslator2 :public CBFunctor2 { public: CBMemberTranslator2(Callee& c, const MemFunc& m) : CBFunctor2(thunk, &c, &m, sizeof(MemFunc)) {} static void thunk(const CBFunctorBase& ftor, P1 p1, P2 p2) { Callee* callee = (Callee*)ftor.callee; MemFunc& memFunc(*(MemFunc*)(void*)(ftor.memFunc)); (callee->*memFunc)(p1, p2); } }; template class CBFunctionTranslator2 :public CBFunctor2 { public: CBFunctionTranslator2(Func f) :CBFunctor2(thunk, 0, f, 0) {} static void thunk(const CBFunctorBase& ftor, P1 p1, P2 p2) { (Func(ftor.func))(p1, p2); } }; template inline CBMemberTranslator2 makeFunctor(CBFunctor2*, Callee& c, TRT(CallType::* const& f)(TP1, TP2)) { typedef TRT(CallType::* MemFunc)(TP1, TP2); return CBMemberTranslator2(c, f); } template inline CBMemberTranslator2 makeFunctor(CBFunctor2*, const Callee& c, TRT(CallType::* const& f)(TP1, TP2)const) { typedef TRT(CallType::* MemFunc)(TP1, TP2)const; return CBMemberTranslator2(c, f); } template inline CBFunctionTranslator2 makeFunctor(CBFunctor2*, TRT(*f)(TP1, TP2)) { return CBFunctionTranslator2(f); } template class CBMemberOf1stArgTranslator2 :public CBFunctor2 { public: CBMemberOf1stArgTranslator2(const MemFunc& m) : CBFunctor2(thunk, (void*)1, &m, sizeof(MemFunc)) {} static void thunk(const CBFunctorBase& ftor, P1 p1, P2 p2) { MemFunc& memFunc(*(MemFunc*)(void*)(ftor.memFunc)); (p1.*memFunc)(p2); } }; template inline CBMemberOf1stArgTranslator2 makeFunctor(CBFunctor2*, TRT(CallType::* const& f)(TP1)) { typedef TRT(CallType::* MemFunc)(TP1); return CBMemberOf1stArgTranslator2(f); } template inline CBMemberOf1stArgTranslator2 makeFunctor(CBFunctor2*, TRT(CallType::* const& f)(TP1)const) { typedef TRT(CallType::* MemFunc)(TP1)const; return CBMemberOf1stArgTranslator2(f); } /************************* two args - with return *******************/ template class CBFunctor2wRet :protected CBFunctorBase { public: CBFunctor2wRet(DummyInit* = 0) {} RT operator()(P1 p1, P2 p2)const { return BC4_RET_BUG(thunk(*this, p1, p2)); } CBFunctorBase::operator int; //for STL typedef P1 first_argument_type; typedef P2 second_argument_type; typedef RT result_type; protected: typedef RT(*Thunk)(const CBFunctorBase&, P1, P2); CBFunctor2wRet(Thunk t, const void* c, const void* f, size_t sz) : CBFunctorBase(c, f, sz), thunk(t) {} private: Thunk thunk; }; template class CBMemberTranslator2wRet :public CBFunctor2wRet { public: CBMemberTranslator2wRet(Callee& c, const MemFunc& m) : CBFunctor2wRet(thunk, &c, &m, sizeof(MemFunc)) {} static RT thunk(const CBFunctorBase& ftor, P1 p1, P2 p2) { Callee* callee = (Callee*)ftor.callee; MemFunc& memFunc(*(MemFunc*)(void*)(ftor.memFunc)); return BC4_RET_BUG((callee->*memFunc)(p1, p2)); } }; template class CBFunctionTranslator2wRet :public CBFunctor2wRet { public: // CBFunctionTranslator2wRet(Func f):CBFunctor2wRet(thunk,0,f,0){} // EBR CBFunctionTranslator2wRet(Func f) :CBFunctor2wRet(thunk, 0, (void*)f, 0) {} static RT thunk(const CBFunctorBase& ftor, P1 p1, P2 p2) { return (Func(ftor.func))(p1, p2); } }; template inline CBMemberTranslator2wRet makeFunctor(CBFunctor2wRet*, Callee& c, TRT(CallType::* const& f)(TP1, TP2)) { typedef TRT(CallType::* MemFunc)(TP1, TP2); return CBMemberTranslator2wRet(c, f); } template inline CBMemberTranslator2wRet makeFunctor(CBFunctor2wRet*, const Callee& c, TRT(CallType::* const& f)(TP1, TP2)const) { typedef TRT(CallType::* MemFunc)(TP1, TP2)const; return CBMemberTranslator2wRet(c, f); } template inline CBFunctionTranslator2wRet makeFunctor(CBFunctor2wRet*, TRT(*f)(TP1, TP2)) { return CBFunctionTranslator2wRet(f); } template class CBMemberOf1stArgTranslator2wRet :public CBFunctor2wRet { public: CBMemberOf1stArgTranslator2wRet(const MemFunc& m) : CBFunctor2wRet(thunk, (void*)1, &m, sizeof(MemFunc)) {} static RT thunk(const CBFunctorBase& ftor, P1 p1, P2 p2) { MemFunc& memFunc(*(MemFunc*)(void*)(ftor.memFunc)); return BC4_RET_BUG((p1.*memFunc)(p2)); } }; template inline CBMemberOf1stArgTranslator2wRet makeFunctor(CBFunctor2wRet*, TRT(CallType::* const& f)(TP1)) { typedef TRT(CallType::* MemFunc)(TP1); return CBMemberOf1stArgTranslator2wRet(f); } template inline CBMemberOf1stArgTranslator2wRet makeFunctor(CBFunctor2wRet*, TRT(CallType::* const& f)(TP1)const) { typedef TRT(CallType::* MemFunc)(TP1)const; return CBMemberOf1stArgTranslator2wRet(f); } /************************* three args - no return *******************/ template class CBFunctor3 :protected CBFunctorBase { public: CBFunctor3(DummyInit* = 0) {} void operator()(P1 p1, P2 p2, P3 p3)const { thunk(*this, p1, p2, p3); } CBFunctorBase::operator int; protected: typedef void (*Thunk)(const CBFunctorBase&, P1, P2, P3); CBFunctor3(Thunk t, const void* c, const void* f, size_t sz) : CBFunctorBase(c, f, sz), thunk(t) {} private: Thunk thunk; }; template class CBMemberTranslator3 :public CBFunctor3 { public: CBMemberTranslator3(Callee& c, const MemFunc& m) : CBFunctor3(thunk, &c, &m, sizeof(MemFunc)) {} static void thunk(const CBFunctorBase& ftor, P1 p1, P2 p2, P3 p3) { Callee* callee = (Callee*)ftor.callee; MemFunc& memFunc(*(MemFunc*)(void*)(ftor.memFunc)); (callee->*memFunc)(p1, p2, p3); } }; template class CBFunctionTranslator3 :public CBFunctor3 { public: CBFunctionTranslator3(Func f) :CBFunctor3(thunk, 0, f, 0) {} static void thunk(const CBFunctorBase& ftor, P1 p1, P2 p2, P3 p3) { (Func(ftor.func))(p1, p2, p3); } }; template inline CBMemberTranslator3 makeFunctor(CBFunctor3*, Callee& c, TRT(CallType::* const& f)(TP1, TP2, TP3)) { typedef TRT(CallType::* MemFunc)(TP1, TP2, TP3); return CBMemberTranslator3(c, f); } template inline CBMemberTranslator3 makeFunctor(CBFunctor3*, const Callee& c, TRT(CallType::* const& f)(TP1, TP2, TP3)const) { typedef TRT(CallType::* MemFunc)(TP1, TP2, TP3)const; return CBMemberTranslator3(c, f); } template inline CBFunctionTranslator3 makeFunctor(CBFunctor3*, TRT(*f)(TP1, TP2, TP3)) { return CBFunctionTranslator3(f); } template class CBMemberOf1stArgTranslator3 :public CBFunctor3 { public: CBMemberOf1stArgTranslator3(const MemFunc& m) : CBFunctor3(thunk, (void*)1, &m, sizeof(MemFunc)) {} static void thunk(const CBFunctorBase& ftor, P1 p1, P2 p2, P3 p3) { MemFunc& memFunc(*(MemFunc*)(void*)(ftor.memFunc)); (p1.*memFunc)(p2, p3); } }; template inline CBMemberOf1stArgTranslator3 makeFunctor(CBFunctor3*, TRT(CallType::* const& f)(TP1, TP2)) { typedef TRT(CallType::* MemFunc)(TP1, TP2); return CBMemberOf1stArgTranslator3(f); } template inline CBMemberOf1stArgTranslator3 makeFunctor(CBFunctor3*, TRT(CallType::* const& f)(TP1, TP2)const) { typedef TRT(CallType::* MemFunc)(TP1, TP2)const; return CBMemberOf1stArgTranslator3(f); } /************************* three args - with return *******************/ template class CBFunctor3wRet :protected CBFunctorBase { public: CBFunctor3wRet(DummyInit* = 0) {} RT operator()(P1 p1, P2 p2, P3 p3)const { return BC4_RET_BUG(thunk(*this, p1, p2, p3)); } CBFunctorBase::operator int; protected: typedef RT(*Thunk)(const CBFunctorBase&, P1, P2, P3); CBFunctor3wRet(Thunk t, const void* c, const void* f, size_t sz) : CBFunctorBase(c, f, sz), thunk(t) {} private: Thunk thunk; }; template class CBMemberTranslator3wRet :public CBFunctor3wRet { public: CBMemberTranslator3wRet(Callee& c, const MemFunc& m) : CBFunctor3wRet(thunk, &c, &m, sizeof(MemFunc)) {} static RT thunk(const CBFunctorBase& ftor, P1 p1, P2 p2, P3 p3) { Callee* callee = (Callee*)ftor.callee; MemFunc& memFunc(*(MemFunc*)(void*)(ftor.memFunc)); return BC4_RET_BUG((callee->*memFunc)(p1, p2, p3)); } }; template class CBFunctionTranslator3wRet :public CBFunctor3wRet { public: CBFunctionTranslator3wRet(Func f) : CBFunctor3wRet(thunk, 0, f, 0) {} static RT thunk(const CBFunctorBase& ftor, P1 p1, P2 p2, P3 p3) { return (Func(ftor.func))(p1, p2, p3); } }; template inline CBMemberTranslator3wRet makeFunctor(CBFunctor3wRet*, Callee& c, TRT(CallType::* const& f)(TP1, TP2, TP3)) { typedef TRT(CallType::* MemFunc)(TP1, TP2, TP3); return CBMemberTranslator3wRet(c, f); } template inline CBMemberTranslator3wRet makeFunctor(CBFunctor3wRet*, const Callee& c, TRT(CallType::* const& f)(TP1, TP2, TP3)const) { typedef TRT(CallType::* MemFunc)(TP1, TP2, TP3)const; return CBMemberTranslator3wRet(c, f); } template inline CBFunctionTranslator3wRet makeFunctor(CBFunctor3wRet*, TRT(*f)(TP1, TP2, TP3)) { return CBFunctionTranslator3wRet(f); } template class CBMemberOf1stArgTranslator3wRet :public CBFunctor3wRet { public: CBMemberOf1stArgTranslator3wRet(const MemFunc& m) : CBFunctor3wRet(thunk, (void*)1, &m, sizeof(MemFunc)) {} static RT thunk(const CBFunctorBase& ftor, P1 p1, P2 p2, P3 p3) { MemFunc& memFunc(*(MemFunc*)(void*)(ftor.memFunc)); return BC4_RET_BUG((p1.*memFunc)(p2, p3)); } }; template inline CBMemberOf1stArgTranslator3wRet makeFunctor(CBFunctor3wRet*, TRT(CallType::* const& f)(TP1, TP2)) { typedef TRT(CallType::* MemFunc)(TP1, TP2); return CBMemberOf1stArgTranslator3wRet(f); } template inline CBMemberOf1stArgTranslator3wRet makeFunctor(CBFunctor3wRet*, TRT(CallType::* const& f)(TP1, TP2)const) { typedef TRT(CallType::* MemFunc)(TP1, TP2)const; return CBMemberOf1stArgTranslator3wRet(f); } /************************* four args - no return *******************/ template class CBFunctor4 :protected CBFunctorBase { public: CBFunctor4(DummyInit* = 0) {} void operator()(P1 p1, P2 p2, P3 p3, P4 p4)const { thunk(*this, p1, p2, p3, p4); } CBFunctorBase::operator int; protected: typedef void (*Thunk)(const CBFunctorBase&, P1, P2, P3, P4); CBFunctor4(Thunk t, const void* c, const void* f, size_t sz) : CBFunctorBase(c, f, sz), thunk(t) {} private: Thunk thunk; }; template class CBMemberTranslator4 :public CBFunctor4 { public: CBMemberTranslator4(Callee& c, const MemFunc& m) : CBFunctor4(thunk, &c, &m, sizeof(MemFunc)) {} static void thunk(const CBFunctorBase& ftor, P1 p1, P2 p2, P3 p3, P4 p4) { Callee* callee = (Callee*)ftor.callee; MemFunc& memFunc(*(MemFunc*)(void*)(ftor.memFunc)); (callee->*memFunc)(p1, p2, p3, p4); } }; template class CBFunctionTranslator4 :public CBFunctor4 { public: // CBFunctionTranslator4(Func f):CBFunctor4(thunk,0,f,0){} //EBR CBFunctionTranslator4(Func f) :CBFunctor4(thunk, 0, (void*)f, 0) {} static void thunk(const CBFunctorBase& ftor, P1 p1, P2 p2, P3 p3, P4 p4) { (Func(ftor.func))(p1, p2, p3, p4); } }; template inline CBMemberTranslator4 makeFunctor(CBFunctor4*, Callee& c, TRT(CallType::* const& f)(TP1, TP2, TP3, TP4)) { typedef TRT(CallType::* MemFunc)(TP1, TP2, TP3, TP4); return CBMemberTranslator4(c, f); } template inline CBMemberTranslator4 makeFunctor(CBFunctor4*, const Callee& c, TRT(CallType::* const& f)(TP1, TP2, TP3, TP4)const) { typedef TRT(CallType::* MemFunc)(TP1, TP2, TP3, TP4)const; return CBMemberTranslator4(c, f); } template inline CBFunctionTranslator4 makeFunctor(CBFunctor4*, TRT(*f)(TP1, TP2, TP3, TP4)) { return CBFunctionTranslator4(f); } template class CBMemberOf1stArgTranslator4 :public CBFunctor4 { public: CBMemberOf1stArgTranslator4(const MemFunc& m) : CBFunctor4(thunk, (void*)1, &m, sizeof(MemFunc)) {} static void thunk(const CBFunctorBase& ftor, P1 p1, P2 p2, P3 p3, P4 p4) { MemFunc& memFunc(*(MemFunc*)(void*)(ftor.memFunc)); (p1.*memFunc)(p2, p3, p4); } }; template inline CBMemberOf1stArgTranslator4 makeFunctor(CBFunctor4*, TRT(CallType::* const& f)(TP1, TP2, TP3)) { typedef TRT(CallType::* MemFunc)(TP1, TP2, TP3); return CBMemberOf1stArgTranslator4(f); } template inline CBMemberOf1stArgTranslator4 makeFunctor(CBFunctor4*, TRT(CallType::* const& f)(TP1, TP2, TP3)const) { typedef TRT(CallType::* MemFunc)(TP1, TP2, TP3)const; return CBMemberOf1stArgTranslator4(f); } /************************* four args - with return *******************/ template class CBFunctor4wRet :protected CBFunctorBase { public: CBFunctor4wRet(DummyInit* = 0) {} RT operator()(P1 p1, P2 p2, P3 p3, P4 p4)const { return BC4_RET_BUG(thunk(*this, p1, p2, p3, p4)); } CBFunctorBase::operator int; protected: typedef RT(*Thunk)(const CBFunctorBase&, P1, P2, P3, P4); CBFunctor4wRet(Thunk t, const void* c, const void* f, size_t sz) : CBFunctorBase(c, f, sz), thunk(t) {} private: Thunk thunk; }; template class CBMemberTranslator4wRet :public CBFunctor4wRet { public: CBMemberTranslator4wRet(Callee& c, const MemFunc& m) : CBFunctor4wRet(thunk, &c, &m, sizeof(MemFunc)) {} static RT thunk(const CBFunctorBase& ftor, P1 p1, P2 p2, P3 p3, P4 p4) { Callee* callee = (Callee*)ftor.callee; MemFunc& memFunc(*(MemFunc*)(void*)(ftor.memFunc)); return BC4_RET_BUG((callee->*memFunc)(p1, p2, p3, p4)); } }; template class CBFunctionTranslator4wRet :public CBFunctor4wRet { public: CBFunctionTranslator4wRet(Func f) : CBFunctor4wRet(thunk, 0, f, 0) {} static RT thunk(const CBFunctorBase& ftor, P1 p1, P2 p2, P3 p3, P4 p4) { return (Func(ftor.func))(p1, p2, p3, p4); } }; template inline CBMemberTranslator4wRet makeFunctor(CBFunctor4wRet*, Callee& c, TRT(CallType::* const& f)(TP1, TP2, TP3, TP4)) { typedef TRT(CallType::* MemFunc)(TP1, TP2, TP3, TP4); return CBMemberTranslator4wRet(c, f); } template inline CBMemberTranslator4wRet makeFunctor(CBFunctor4wRet*, const Callee& c, TRT(CallType::* const& f)(TP1, TP2, TP3, TP4)const) { typedef TRT(CallType::* MemFunc)(TP1, TP2, TP3, TP4)const; return CBMemberTranslator4wRet(c, f); } template inline CBFunctionTranslator4wRet makeFunctor(CBFunctor4wRet*, TRT(*f)(TP1, TP2, TP3, TP4)) { return CBFunctionTranslator4wRet (f); } template class CBMemberOf1stArgTranslator4wRet :public CBFunctor4wRet { public: CBMemberOf1stArgTranslator4wRet(const MemFunc& m) : CBFunctor4wRet(thunk, (void*)1, &m, sizeof(MemFunc)) {} static RT thunk(const CBFunctorBase& ftor, P1 p1, P2 p2, P3 p3, P4 p4) { MemFunc& memFunc(*(MemFunc*)(void*)(ftor.memFunc)); return BC4_RET_BUG((p1.*memFunc)(p2, p3, p4)); } }; template inline CBMemberOf1stArgTranslator4wRet makeFunctor(CBFunctor4wRet*, TRT(CallType::* const& f)(TP1, TP2, TP3)) { typedef TRT(CallType::* MemFunc)(TP1, TP2, TP3); return CBMemberOf1stArgTranslator4wRet(f); } template inline CBMemberOf1stArgTranslator4wRet makeFunctor(CBFunctor4wRet*, TRT(CallType::* const& f)(TP1, TP2, TP3)const) { typedef TRT(CallType::* MemFunc)(TP1, TP2, TP3)const; return CBMemberOf1stArgTranslator4wRet(f); } #endif //CALLBACK_HPP