Overloaded member function pointer

I am trying to store member function pointers with patterns like this: (This is a simplified version of my real code)

template<class Arg1> void connect(void (T::*f)(Arg1)) { //Do some stuff } template<class Arg1> void connect(void (T::*f)()) { //Do some stuff } class GApp { public: void foo() {} void foo(double d) {} }; 

Then I want to do the following for each overloaded method in GApp:

 connect(&GApp::foo); 

Calling this for foo() is fine, but how can it be called for foo(double d) ? Why does the following not work?

 connect((&GApp::foo)(double)); 

It will give me

Syntax error: 'double' must precede ')'

I do not understand the syntax to use here. It may be stupid, but can someone help me with this?

+6
source share
6 answers

Your code, as written, does not compile. I made some “assumptions” about what you wanted to do, and changed the code.

To summarize, you can call the correct function by explicitly specifying the type of the function parameter:

 connect<double> (&GApp::foo); 

If the connection methods are members of the class template, then you only need to specify the class type once:

 template <typename T> class A { public: template<class Arg1> void connect(void (T::*f)(Arg1)) { //Do some stuff } void connect(void (T::*f)()) { //Do some stuff } }; class GApp { public: void foo() {} void foo(double d) {} }; int main () { A<GApp> a; a.connect (&GApp::foo); // foo () a.connect<double> (&GApp::foo); // foo (double) } 

UPDATE:

In response to a new code sample, all information is transmitted. The “rare” case is the signal_void case, since there is a template argument here, but the member function does not work. Therefore, we have a special case, that example, and then we are done. Now compilation is done:

 template <class Arg = void> class signal {}; signal<double> signal_double; signal<> signal_void; // Arg1 is deduced from signal<Arg1> and then we use it in the declaration // of the pointer to member function template<class T, class Arg1> void connect ( signal<Arg1>& sig, T& obj, void (T::*f)(Arg1) ) {} // Add special case for 'void' without any arguments template<class T> void connect (signal<> & sig, T& obj, void (T::*f)()) {} void bar () { GApp myGApp; //Connecting foo() connect(signal_void, myGApp, &GApp::foo); // Matches second overload //Connecting foo(double) connect(signal_double, myGApp, &GApp::foo); // Matches first overload } 
+6
source

C ++ programming language, 3E, section 7.7, p. 159:

You can take the address of an overloaded function by assigning or initializing a pointer to a function. In this case, the target type is used to select from a set of overloaded functions. For example:

 void f(int); int f(char); void (*pf1)(int) = &f; // void f(int); int (*pf2)(char) = &f; // int f(char); void (*pf3)(char) = &f; // error: no void f(char) 

As far as I know (not tested), the same goes for member functions. Thus, the solution should probably be split into two lines:

 connect((&GApp::foo)(double)); 

becomes:

 void (GApp::*tmp)(double) = &GApp::foo; connect(tmp); 

Never call tmp variables; -)

I would suggest that newacct cast is also safe for the same reason. Casting on void (GApp::*)(double) is defined the same as initializing the temporary type void (GApp::*)(double) . Since the expression used to initialize it is &GApp::foo , I would expect the same magic to apply to the cast, applicable to any other initialization with an overloaded function. Stroustup does not say “initializing a function pointer variable”, he says “initializing a function pointer”. Thus, this should include temporary files.

So, if you prefer single line:

 connect((void (GApp::*)(double))(&GApp::foo)); 

However, I assume that the standard has the same idea of ​​consistency as I did, and I have not tested it.

+5
source

You can try to explicitly place the pointer so that it knows which one to choose, for example:

 connect((void (GApp::*)(double))&GApp::foo); 

disclaimer: did not check it

+1
source

It works,

  typedef void (GApp::*MemberFunctionType)(double); MemberFunctionType pointer = &GApp::foo; connect(MemberFunctionType); 

Why is this?

EDIT

hmm .. yes. This is the same as newacct solution. Can someone give a solution pls?

0
source

Using boost :: function library ...

 #include <boost/function.hpp> template<class Arg1> void connect(boost::function1<void, Arg1*> fn) { //Do some stuff } template<class Arg1> void connect(boost::function2<void, Arg1*, double> fn) { //Do some stuff } class GApp { public: void foo() {} void foo(double d) {} }; int main() { boost::function1<void,GApp*> f1 = (void (GApp::*)(void)) &GApp::foo; boost::function2<void,GApp*,double> f2 = (void (GApp::*)(double)) &GApp:foo; connect(f1); connect(f2); return 0; } 
0
source

My original code is as follows:

connectors ....

 template<class T, class Arg1> void connect(signal<Arg1>& sig,T& obj, void (T::*f)()) { // sig.insert(new GFunction<T, Arg1>(&obj,f)); } template<class T, class Arg1 void connect(signal<Arg1>& sig,T& obj, void (T::*f)(Arg1)) { // sig.insert(new GFunction<T, Arg1>(&obj,f)); } 

Signals ...

 signal<double> signal_double; signal<> signal_void; 

Application ...

 class GApp { public: void foo() {} void foo(double d) {} }; 

Finally, the connection ...

 //Connecting foo() connect(signal_void, myGApp, &GApp::foo()); //Ok //Connecting foo(double) connect(signal_double, myGApp, &GApp::foo()); // but ERROR! 

Template classes exist for signals (which are not mentioned here). Hopefully now the situation is clearer. (or is it the same as previouse?). This second connection will work if foo () does not exist (only foo (double)). This is what my code hurt me. :(

0
source

All Articles