| View previous topic :: View next topic |
| Author |
Message |
hcavolsdsadgadsg I'm a spammer
Reputation: 26
Joined: 11 Jun 2007 Posts: 5801
|
Posted: Thu Dec 31, 2009 6:10 am Post subject: C++, member function pointers, safe cast? |
|
|
Tell me, is it safe to cast from one member function pointer to another of a different class? I'm relying on casting a member function pointer to a sort of "generic" type.
| Code: | something like
int main()
{
Base b;
Test t;
b.exec(reinterpret_cast<Base::func_ptr>(&Test::dong));
return 0;
} |
sleep time.
|
|
| Back to top |
|
 |
tombana Master Cheater
Reputation: 2
Joined: 14 Jun 2007 Posts: 456 Location: The Netherlands
|
Posted: Thu Dec 31, 2009 7:48 am Post subject: |
|
|
| I don't understand it completely but I guess the functions need to have the same number of arguments and calling convention. Do your functions have that?
|
|
| Back to top |
|
 |
Flyte Peanuts!!!!
Reputation: 6
Joined: 19 Apr 2006 Posts: 1887 Location: Canada
|
Posted: Thu Dec 31, 2009 3:19 pm Post subject: |
|
|
I think the better question is why are you even doing this? I can't even think of a reason to do so. If you need to pass around a pointer to a member for a specific instance of a class look into mem_fun() or mem_fun_ref() (or their boost equivalants).
If you told us what you were trying to accomplish, maybe I could show you a better way.
|
|
| Back to top |
|
 |
hcavolsdsadgadsg I'm a spammer
Reputation: 26
Joined: 11 Jun 2007 Posts: 5801
|
Posted: Thu Dec 31, 2009 6:05 pm Post subject: |
|
|
| tombana wrote: | | I don't understand it completely but I guess the functions need to have the same number of arguments and calling convention. Do your functions have that? |
yes, this does need to be met.
| Flyte wrote: | I think the better question is why are you even doing this? I can't even think of a reason to do so. If you need to pass around a pointer to a member for a specific instance of a class look into mem_fun() or mem_fun_ref() (or their boost equivalants).
If you told us what you were trying to accomplish, maybe I could show you a better way. |
Think quake console. I'm just running through as a learning exercise mainly. I keep an std::list of structs that holds the name and pointer when I add a function. If the name matches what the user enters, that function gets called.
Originally I just ended up wrapping the member functions in a static function and passing that, this is kinda a nasty solution.
My compiler supports std::function / bind so I tried this next. Bind with a placeholder argument works fine, even if it is a little verbose. I think this might be the way to go ultimately.
But I was dicking with something like this last night:
| Code: | #include <iostream>
#include <string>
class Base
{
public:
typedef void (Base::*func_ptr)(const void* arg);
void Base::exec(func_ptr ptr, const std::string& arg)
{
(this->*ptr)(&arg);
}
};
class Test
{
public:
int butt;
void Test::dong(const std::string& str)
{
std::cout << str;
butt = 1;
}
};
int main()
{
Base b;
Test t;
b.exec(reinterpret_cast<Base::func_ptr>(&Test::dong), "what");
return 0;
} |
|
|
| Back to top |
|
 |
Flyte Peanuts!!!!
Reputation: 6
Joined: 19 Apr 2006 Posts: 1887 Location: Canada
|
Posted: Thu Dec 31, 2009 7:06 pm Post subject: |
|
|
So something like this.
| Code: | #include <iostream>
#include <map>
#include <string>
#include <algorithm>
#include "boost/shared_ptr.hpp"
using namespace std;
template <typename ArgType, typename ReturnType = void>
struct UnaryFunctor {
virtual ReturnType operator()(ArgType) = 0;
};
struct PrintFunctor : UnaryFunctor<const string&> {
void operator()(const string & someArg) {
cout << someArg << endl;
}
};
struct ReversePrintFunctor : UnaryFunctor<const string&> {
void operator()(const string & someArg) {
const string reverse(someArg.rbegin(), someArg.rend());
cout << reverse << endl;
}
};
class FunctorProvider {
map<string, boost::shared_ptr<UnaryFunctor<const string&>>> funcs_;
public:
template <class T>
bool Register(const string & command) {
if(funcs_.find(command) == funcs_.end()) {
funcs_[command] = boost::shared_ptr<UnaryFunctor<const string&>>(new T);
return true;
}
return false;
}
bool Execute(const string & command, const string & arg) {
if(funcs_.find(command) != funcs_.end()) {
(*funcs_[command])(arg);
return true;
}
return false;
}
};
int main()
{
FunctorProvider funcDict;
funcDict.Register<PrintFunctor>("print");
funcDict.Register<ReversePrintFunctor>("reverse");
funcDict.Execute("print", "Hello world!");
funcDict.Execute("reverse", "Hello world!");
return 0;
} |
Last edited by Flyte on Thu Dec 31, 2009 11:15 pm; edited 1 time in total |
|
| Back to top |
|
 |
hcavolsdsadgadsg I'm a spammer
Reputation: 26
Joined: 11 Jun 2007 Posts: 5801
|
Posted: Thu Dec 31, 2009 7:23 pm Post subject: |
|
|
aaah that looks excellent
I have almost zero experience with boost, time to do some reading.
Looks like shared_ptr is available in tr1 as well, rad
|
|
| Back to top |
|
 |
Flyte Peanuts!!!!
Reputation: 6
Joined: 19 Apr 2006 Posts: 1887 Location: Canada
|
Posted: Thu Dec 31, 2009 7:33 pm Post subject: |
|
|
| slovach wrote: | aaah that looks excellent
I have almost zero experience with boost, time to do some reading.
Looks like shared_ptr is available in tr1 as well, rad |
shared_ptr is just a reference counted pointer that gets deleted when nothing is using it. I use them when I don't want to have to deal with dynamic memory, but they really shine when you use them with the std containers as both auto_ptr and scoped_ptr break in them.
A lot of the boost library is being added into the next C++ revision; they are very handy and I would recommend anyone who is serious about C++ learn to use some of them. Also, since you are doing text parsing, I'd recommend Boost.Spirit.
|
|
| Back to top |
|
 |
|