ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Sorry for the stupid heading of the thread, i could not think any better.
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:
Code:
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)
Code:
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 )
Code:
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.
Personally I would use an existing functor library like Loki, Boost or an implementation of C++0x. Using one of these it is possible to register any of the following function, this example uses Loki.
The code in main can be encapsulated into yet another class derived from function_wrapper so that it can encapsulate any object. This is a very reliable pattern, but one problem with it is that the name of the function must be fixed. In any case, there is absolutely no way that class1::function and class2::function can be derived from a single function pointer; you need to use something like this.
ta0kira
Whilst the code posted by ta0kira would work for this instance I would have to say it is not a nice implementation due to it not being generic enough. It is the fundamentals of how functors are done yet any change to the function signature requires a change of the base class or worst still if you have many signatures in a project then many different base "wrappers" hand coded, for example if you wanted a return type or parameters. Added to this that all functions have to be member functions and have the same name and it is reinventing a well defined wheel which good libraries with good support all ready implement.
Yeah, I didn't read the thread very well I guess. I actually wrote something several years ago that did what ptr in your post does and I sort of misremembered how I did it. Regardless, it's often better to use something already built and maintained.
ta0kira
Thanks for your replies, i had installed boost recently on my system. For the time being i am implementing the idea provided by ntubski as i need this thing done by the end of day. However, soon i would go through boost::function and would use that in future.
@ta0kira But don't you think that such libraries would also be using void* pointer and casting in their implementation ?
Quote:
void* is a terrible idea in C++. That's what templates and abstract classes are for!
Are templates an answer to explicit casting ?( correct me if i am wrong )
One more thing i would like to mention. I have found the boost libraries to be a source of extremely good learning material, making the life of an application programmer quite easy.Boost libraries come with documentation on how to *use* the library but no information about how it is implemented(boost after all is not meant for tutoring or mentoring)
However i would also like to learn how things are implemented( and designed ) in such expertly written libraries. I don't want to be a mere user of such libraries and so want to improve my skill by reading code written by experienced people and then compare with what i would have thought about implementing the same thing and thereby learn in the process.
Although boost libraries come with source code, if i begin reading a library say asio, it is dependent on other boost libraries like boost::system ,boost::function(i am not sure about that)
and so most of the time i get lost in details. There are no pointers as how to read code, i mean where to start first.
I can comprehend most of the code that i read except these library dependencies. Any hints on how i can tackle that problem ?
I know that learning programming is not like following a list of sequentional steps from beginning to end and is not a straight path. It takes time and patience. However if any of you has ever tried learning from code written by others, please shed some light on your experience on how to do it.
Last edited by lali.p; 10-24-2008 at 01:21 AM.
Reason: grammatical error
Here's a timer class (Timer.hpp) that I tinkered with a couple of years ago. I never used it for anything; maybe it can provide you with some ideas. (Btw, sorry for the lack of documentation; hopefully the TestTimer.cpp test-program will serve as a guide).
Timer.hpp (provides for blocking or non-blocking timer, with option to repeat):
PHP Code:
/* # Copyright (C) 2008 David M. Whitney (aka "dwhitney67") # # This program is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation, either version 3 of the License, or (at your option) any later # version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see <http://www.gnu.org/licenses/>. */
#ifndef TIMER_HPP #define TIMER_HPP
#include <sys/types.h> #include <sys/select.h> #include <unistd.h> // for fork() #include <cstdlib> // for exit() #include <iostream>
int seconds; int microseconds; TimerType type; int repeats; T functor; };
#endif
WaitTimer.hpp (a blocking timer):
PHP Code:
/* # Copyright (C) 2008 David M. Whitney (aka "dwhitney67") # # This program is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation, either version 3 of the License, or (at your option) any later # version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see <http://www.gnu.org/licenses/>. */
#ifndef WAIT_TIMER_HPP #define WAIT_TIMER_HPP
#include "Timer.hpp" #include <iostream>
class WaitTimer { private: class CallbackForTimer { public: CallbackForTimer() {} void operator()() { /* nothing to do */ } };
/* # Copyright (C) 2008 David M. Whitney (aka "dwhitney67") # # This program is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation, either version 3 of the License, or (at your option) any later # version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see <http://www.gnu.org/licenses/>. */
@ta0kira But don't you think that such libraries would also be using void* pointer and casting in their implementation ?
If it can be done safely, it can be done without void*. Sure, that's really what's used internally, but there is almost always a way to make things work with templates. I've created some very elaborate function pointer systems without using a single void*. Though not documented, here is my experiment with function pointers from many years ago: http://sourceforge.net/projects/afunct-ta0kira/. No coding standards, I admit, but it's built almost entirely partial specialization. I hope my skills have improved since then
ta0kira
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.