Re: Function pointer and functor problem
On Oct 24, 3:31 pm, "lali.cpp" <lali....@gmail.com> wrote:
Hi
I am having a doubt about function pointers and functors. I know that
the signatures of a function pointer and a pointer to a class member
function are different. However signature of a global function and
signature of a static class function are compatible.
Here is what i want to achieve:
There are 2 unrelated classes say A and B ( they are unrelated and
hence i don't want to make them part of any inheritance structure)
I have written a timer class in which i can register multiple timers,
it takes a timeout value and a function pointer that would be invoked
when the timer times out i.e basically i want a callback mechanism on
timeout. So internally the timer is using a queue to store all these
function pointer and all these function pointers have signature void
(*ptr)( );
So the queue would be like:
typedef void (*ptr)( );
queue<ptr> timer_queue;
The problem is i want to invoke the member function of classes A and
B when a timer expires so that i can change the state of object of
class A or B.
Let me make it clear( i really suck in communication, sorry for that)
class A
{
public:
A( ):a(5)
{
}
void timerExpired( )
{
cout<<a;
}
private:
int a
};
class B
{
public:
B():name("JOHN")
{
}
void timerExpired( )
{
cout<<name;
}
private:
string name;
};
So i want a timer that can help me code the below code :( the
following code may not be syntactically correct )
Timer timer;
A obj_of_a;
B obj_of b
// please remember that timer uses a queue of function pointers
timer.registerTimer(A::timerExpired,6)// expires after 5 seconds
timer.registerTimer(B::timerExpired,2) // expires after 2 seconds
Problem is that these two functions are not static and if i make them
static how would i change the state of the objects ( static functions
don't have this pointer)
Is it even possible i.e to store pointers to member functions (of
different classes) in a queue and invoke them.
It can be done if i make A and B derived from class C containing a
virtual function timerExpired and then storing a functor instead of a
function pointer but i don't want to do that as in my case A and B are
not at all related.
Can it be done somehow using wrapper static functions of classes A and
B ??
Please provide some hint or guidance.
Thanks a lot for your patience
Regards
lali
Yes, you can use a simple template trick to wrap your member function
calls into a static function. This static function will take a void*
pointer, reinterpret_cast it into your class type pointer and then
call the TimerExpired() call on it. Since reinterpret_cast is
dangerous we will need to wrap this in a struct that will make this
type safe by construction.
This isn't tested on the compiler but I hope that you'll be able to
understand the concept:
// Function that will call your TimerExpired, not typesafe since it
blindingly assumes
// that the pointer your passing is of type T*
template<typename T>
static void CallTimerExpiredOnThisPtr(void* this_ptr) {
reinterpret_cast<T*>(this_ptr)->TimerExpired();
}
typedef void(*TimerExpiredFunPtr)(void); // typedef function pointer
// Struct wraps the function template so that it is typesafe.
struct TimerExpiredCallback {
// templated constructor will bind to the appropriate TimerExpired<>
function
template<typename T>
TimerExpiredCallback(T* this_ptr)
: m_this_ptr(this_ptr) {
m_fun_ptr = CallTimerExpiredOnThisPtr<T>; // bind to appropriate
function
}
// in turn will call your TimerExpired()
void CallTimerExpired() { m_fun_ptr(m_this_ptr); }
private:
friend class std::vector<TimerExpiredCallback>;
TimerExpiredCallback() {} // needed for std::vector
void*const m_this_ptr;
TimerExpiredFunPtr m_fun_ptr;
};
int main() {
A a;
B b;
std::vector<TimerExpiredCallback> callbacks;
callbacks.push_back(TimerExpiredCallback(&a));
callbacks.push_back(TimerExpiredCallback(&b));
for(int i = 0; i<callbacks.size(); ++i)
{ callbacks[i].CallTimerExpired(); }
}
Cheers,
~Z~
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]