I was learning some new concepts in C++ today and heard about, yet not really understood completely, delegates.
After this I tried to implement something like this:
1 2 3 4 5 6 7 8 9 10 11
template<typename T>
class delegate{
public:
private:
T _m_fpFunction;
};
int main(int argc, char* argv[]){
delegate<void (*)(void)> d;
return 0;
}
Works fine, but there's no "real" functionality. What I want to accomplish, is to create a class that will accept a member function pointer of any class. As some of you might already know, member function pointers have this restriction I'm trying to, should I say, "broke". The use of this class would be like the following:
1 2 3 4 5 6 7 8 9 10
int main(int argc, char* argv[]){
delegate<void (*)(void)> d;
void(Foo::*fptr)(void);
d = fptr;
void(Foo2::*fptr2)(void);
d = fptr2;
return 0;
}
But the question is, how to do this? Any suggestions?
Ah, I see the problem.
So, you have the delegate class instantiated based on a type of function pointer as its template argument, and you want operator= to take this kind of function pointer but as a member-function pointer.
Maybe something like this instead? It seems hard to deal with a function like that because you can't know how many parameters to give it...
struct A
{
void fct(int i)
{
std::cout << "A call" << i << std::endl;
}
};
struct B
{
void fct(int i)
{
std::cout << "B call" << i * 2 << std::endl;
}
};
int main()
{
try
{
A a;
B b;
Delegate<void(int)> d = &A::fct;
d(a, 5);
d = &B::fct;
d(b, 5);
}
catch (std::exception& e)
{
std::cout << e.what() << std::endl;
}
return 0;
}
It work but it is limited because objects passed to operator() must have exactly the same type, the type hierarchy is not taked into account.
Feel free to ask if my code is not clear.
If you don't have variadic templates, remove it or use macros instead.
Excellent suggestions & implementations. Thanks a lot! It takes a while to explore these...
Anyway, L B's code seems quite simple yet helpful, although aquaz's code might be the most complete so far in terms of the functionality I'm looking for, but when I look at the code... Sheesh, member function pointers seem to be quite complex indeed! Great piece of code, but could there be a non-RTTI approach to achieve the goal?
¿Do you realize that the types are different?
¿How are you planning to use it?
Yes, I realize the types are different. I'm trying to break this restriction, and it seems that there are different possibilities - I'm just looking for the most efficient and the most readable solution. I don't expect you to write the whole class, although I will totally appreciate it.
typename ...Args is variadic template(c++11). It means there is an unspecified number of templates arguments. Then you can use it with Args... to expand the types like in class Delegate<R(Args...)> where I use template specialization to get the return type and the parameter type of the signature.
Then if for example I write Delegate<int(char, float)> d, R will be int and Args will be char, float. This technique is very useful to parse template parameters of the form T(A, B(...), ...).
In
1 2
template <typename T>
R operator() (T& obj, Args&&... params)
I expand Args to make operator() have the right signature. So Delegate<int(char, float)> d will produce something like
OK, no wonder my compiler couldn't compile the code correctly. I don't have C++11 support for my compiler (Code::Blocks) yet. What compiler are you using?
I used code blocks to compile the code so it should work. I forget to add includes, i will add them to my code, maybe that's why you cannot compile.
Take a look at your compiler options, i selected gnu gcc.
No, Delegate<void(int)> d = &A::fct; is fine. I'm pretty sure it's valid in old c++ because boost use it. But you must use template specialization to take profit of it like i explained in 5 posts above.
template<typename T> class C{};
C<void(int)> c; //error
So, I guess it's only C++11. It would make sense since the compiler *should* be able to automagically know that is it a function pointer even without the (*) to help it out.
Did you really tried to compile it? It compile fine in my VC++ 2008 with language extensions disabled. I seriously doubt boost::spirit is written in C++11.
void(int) is not the type of a function pointer but a function signature, you can use it for many other things than function pointers.