templates and pointers to member functions - c++

I would like to use and work with pointer to some member function and I also want to be able to call that (or other) member function back.
Lets say, I have headers like this:
class A{
public:
template<class T> void Add(bool (T::*func)(), T* member){
((member)->*(func))();
}
};
class B{
public:
bool Bfoo(){return 1;}
void Bfoo2(){
A a;
a.Add(Bfoo, this);
}
};
and cpp like this:
main(){
B f;
f.Bfoo2();
}
I've got following error:
main.h(22) : error C2784: 'void __thiscall A::Add(bool (__thiscall
T::*)(void),T *)' : could not deduce template argument for 'overloaded
function type' from 'overloaded function type'
I need to call A::Add from many classes (and send information about class method and its instance) so that's why I want to use templates
Using Microsoft Visual C++ 6.0. What am I doing wrong? I cannot use boost.

In my opinion, right way to do what you need is to use inheritance, for example:
class A {
virtual void Add() = 0;
}
class B : public A {
void Add() {...}
}
class C : public A {
void Add() {...}
}
So in your main you can do:
A* a = new B();
a->Add(); /* this call B::Add() method */

You need to pass an address of function
a.Add(&B::Bfoo, this);

Related

How can I assign and use function pointers of 2 different classes between among them?

I'm developing a protocol stack and I have wrote a different levels with classes they have functions and function pointers for connect different levels among them.
I have problems to manage and assign function pointers. The situation is similar to the following (simplified):
File baseA.h:
class baseA
{
public:
virtual void fnc1(void)=0;
void (B::*fnc2)(void)=NULL;
};
File A.h:
class A:baseA
{
public:
void task(void);
void fnc1(void);
void (B::*fnc2)(void)=NULL;
};
File A.cpp:
void A::task()
{
if(this->fnc2!=NULL)
this->fnc2();
}
void A::fnc1(void)
{
//Do something
}
File B.h:
class B
{
public:
void task(void);
void fnc1(void);
void (baseA::*fnc2)(void);
};
File B.cpp:
void B::task(void)
{
if(this->fnc2!=NULL)
this->fnc2();
}
void B::fnc1(void)
{
//Do something
}
Main function:
main(void)
{
A instA;
B instB;
instA.fnc2 = instB.fnc1;
instB.fnc2 = instA.fnc1;
while(1)
{
instA.task();
instB.task();
}
}
I have two problems:
in the function main, when I assign the function pointers , the compiler return me the errors "cannot convert 'B::fnc1' from type 'void (B::)()' to type 'void (*)()'" (for instA.fnc2 = instB.fnc1;) and "cannot convert 'A::fnc1' from type 'void (A::)()' to type 'void (*)()'" (for instB.fnc2 = instA.fnc1;).
when I use the function pointers, inside the task functions, the compiler return me the error "must use '.*' or '->*' to call pointer-to-member function in '((A*)this)->A::fnc2 (...)', e.g. '(... ->* ((A*)this)->A::fnc2) (...)'". I have tried to use (this->*fnc2)(); but in this case compiler return me the error "pointer to member type 'void (B::)()' incompatible with object type 'A'"
I have tried to search and apply the different suggestion found in internet but I could not solve the problem.
What's my mistakes?
Member function pointers syntax is not trivial, but you have a major understanding problem here: it is something that point to a method of a given class. That means that:
you load it with a reference to a class and not to a (possibly polymorphic) object
you call it on an object of its class
First is simple, you must use this in your main:
instA.fnc2 = &B::fnc1;
instB.fnc2 = &baseA::fnc1; // and not A::fnc1 since fnc1 is only declared in baseA
For the second point, you will need a B object (or ref. or pointer) in A and a A object (or ref. or pointer) in B. I will use pointers here for simplicity:
class A:baseA
{
public:
void task(void);
void fnc1(void);
void (B::*fnc2)(void)=NULL;
B* b;
};
void A::task()
{
if(this->fnc2!=NULL && b != NULL)
(b->*fnc2)(); // note the parentheses to avoid a syntax error
}
class B
{
public:
void task(void);
void fnc1(void);
void (baseA::*fnc2)(void);
A* a;
};
void B::task(void)
{
if(this->fnc2!=NULL && a != NULL)
(a->*fnc2)();
}

c++ passing class method as argument to a class method with templates

I'm trying to pass a class method to another class method using template, and cannot find any answer on how to do (no C++11, boost ok):
I simplified the core problem to :
class Numerical_Integrator : public Generic Integrator{
template <class T>
void integrate(void (T::*f)() ){
// f(); //already without calling f() i get error
}
}
class Behavior{
void toto(){};
void evolution(){
Numerical_Integrator my_integrator;
my_integrator->integrate(this->toto};
}
I get as error:
error: no matching function for call to ‘Numerical_Integrator::integrate(<unresolved overloaded function type>)’this->toto);
note: no known conversion for argument 1 from ‘<unresolved overloaded function type>’ to ‘void (Behavior::*)()’
Thank you.
Bonus: What about with arguments ?
class Numerical_Integrator{
template <class T, class Args>
double integrate(void (T::*f)(), double a, Args arg){
f(a, arg);
}
}
class Behavior{
double toto(double a, Foo foo){ return something to do};
void evolution(){
Foo foo;
Numerical_Integrator my_integrator;
my_integrator->integrate(this->toto, 5, foo};
}
Your question is not really about passing a class method as part of a template parameter.
Your question is really about correctly invoking a class method.
The following non-template equivalent will not work either:
class SomeClass {
public:
void method();
};
class Numerical_Integrator : public Generic Integrator{
void integrate(void (SomeClass::*f)() ){
f();
}
}
A class method is not a function, and it cannot be invoked as a function, by itself. A class method requires a class instance to be invoked, something along the lines of:
class Numerical_Integrator : public Generic Integrator{
void integrate(SomeClass *instance, void (SomeClass::*f)() ){
(instance->*f)();
}
}
You need to revise the design of your templates, and/or class hierarchies in order to resolve this first. Once you correctly implement your class method invocation, implementing a template should not be an issue.

Passing a method pointer for a new method to base class

I'd like to be able to call any arbitary method (which are generic methods) defined in a derived class from the base class. The base class doesn't know about them. I'd somehow like to get this pointer and the virtual table offset and be able to call it. Class A doesn't actually need to be the base class, it could be a separete class which doesn't know anything about B but needs to call the methods. Is it possible?
class A
{
public:
typedef void (A::*Method)();
void call(Method p)
{
//...
}
};
class B : public A
{
public:
virtual void meth1()
{
}
virtual void meth2()
{
}
virtual void test()
{
call(&TestTask::meth1);
call(&TestTask::meth2);
}
};
Errors:
test.cpp:420:30: error: no matching function for call to ‘B::call(void (TestTask::*)())’
call(&TestTask::meth1);
^
test.cpp:420:30: note: candidate is:
test.cpp:402:10: note: void A::call(A::Method)
void call(Method p)
^
test.cpp:402:10: note: no known conversion for argument 1 from ‘void (TestTask::*)()’ to ‘A::Method {aka void (A::*)()}’
test.cpp:421:30: error: no matching function for call to ‘B::call(void (TestTask::*)())’
call(&TestTask::meth2);
Non-static member functions need an object to act on, so you can't simply call the member-function pointer by itself. You could define a template to call a member of any class, given an object of that class:
template <class Class>
void call(Class & c, void (C::*method)()) {
(c.*method)();
}
If that's not what you want, then you'll need to clarify what you do want.
You can use the CRTP pattern to accomplish what you are trying.
template <typename T> struct A
{
typedef void (T::*Method)();
void call(Method m)
{
(static_cast<T*>(this)->*m)();
}
};
struct B : A<B>
{
void meth1(){}
void meth2(){}
void test()
{
call(&B::meth1);
call(&B::meth2);
}
};

Function pointer in class A to member function from class B

I'm searching a solution for this for a few days now. Didn't find any question related enough to answer regrettably so here is my question.
Consider the next code:
// dummy class A
class A {
public:
void aFunction() { // <- this is the function I want to point at
cout << "aFunction() is called\n";
}
};
class B {
public:
template <class Class> // get a function pointer
void setFunction( void (Class::*func)() ) {
p_func = func;
}
void (*p_func)(); // the function pointer
}
int main() {
B obj;
objb.setFunction(&A::aFunction);
return 0;
}
I have a compilation error in setFunction() on p_func = func;:
cannot convert from 'void (__thiscall A::* )(void)' to 'void (__cdecl *)(void)'
And I don't seem to be able to get rid of it in any way. I know it has something to do with those invisible this pointers (__thiscall and __cdecl), but I don't know how to handle these. I tried making the member variable p_func a class template too (void (Class::*p_func)()) so it would have the same structure, but it that seems to be illegal to have 2 class templates in one class (why?), thus isn't the correct solution. This time the compiler complains about:
multiple template parameter lists are not allowed
This method (without the template) works perfectly on global functions (which is the workaround I currently use) and I saw the use of it in a library (sfgui), so it should be perfectly possible.
To have some context over why I'd want this: I'm trying to create a button. This button should be able to call whatever function I'd like. For now, I'd like it to call the start() function of an animation class I'm making.
p.s.: I know this example is useless since I can't run p_func: the function isn't static. I still need to add an object pointer (setFunction( void (Class::*func)(), Class* )), but that does not seem to be a problem. And I know about typedef to make a function pointer more readable, but not with a class template.
EDIT
After some more research I think the answer I need not the answer to this question, but rather another one. For once, I noticed that multiple template <class Class> is in fact allowed. However, it is not allowed on member variables since the compiler can't possibly know which class he'll need to use which probably is the reason for the error
multiple template parameter lists are not allowed
which is an odd description. Thanks anyway for the help, you did gave me a better insight.
You cannot convert a pointer-to-member Class::*func to a normal function pointer. They are of different types.
You should turn this:
void (*p_func)(); // the function pointer
into this:
void (class::*p_func)(); // the function pointer
You could also use a std::function<void()> and use boost::bind to bind it.
std::function<void()> fun = boost::bind(class::member_fun, args);
EDIT
What about making your B class a template so you can do this:
#include<iostream>
class A {
public:
void aFunction() { // <- this is the function I want to point at
std::cout << "aFunction() is called\n";
}
};
template<class T>
class B {
public:
void setFunction( void (T::*func)() ) {
p_func = func;
}
void (T::*p_func)(); // the function pointer
void callfunc()
{
(t.*p_func)(); //call pointer to member
}
private:
T t;
};
int main() {
B<A> obj;
obj.setFunction(&A::aFunction);
return 0;
}
Live Example
I found the complete answer myself while searching for a way to save *objects of an unknown type without using templates or void pointers which has been answered here. The solution is a bit dodgy, because you'll have to create a dummy parent which allows for certain conversions.
The idea is that you create a Parent and every object that is allowed to be pointed to must inherit from it. This way you can create a pointer as Parent *obj which can hold multiple types of objects, but of course only classes that inherit from Parent.
The same applies for function pointers. If you define your pointer as void (Parent::*func)() as member variable. You can ask the user a template function pointer template <class Class> setFunction( void (Class::*f)() ), which can hold any pointer to any class. Now you need to cast the function pointer to the desired class, Parent: static_cast<void(Parent::*)()>(f). Mind that this only works when Class inherits from Parent. Otherwise you'll get a compilation error.
Minimal Working Example
#include <iostream>
using namespace std;
// dummy class Parent
class Parent {};
// class A
class A : public Parent { // Mind the inheritance!
public:
A(int n) : num(n) {}
void print() { // <- function we want to point to
cout << "Number: " << num << endl;
}
int num;
}
// class B, will hold the 2 pointers
class B {
public:
B() {}
template <class Class> // will save the function and object pointer
void setFunction( void (Class::*func)(), Class *obj) {
function = static_cast<void(Parent::*)()>(func);
object = obj;
}
void execFunction() { // executes the function on the object
(object->*function)();
}
void (Parent::*function)(); // the function pointer
Parent *object; // the object pointer
}
int main() {
A a(5);
B b;
b.setFunction(&A::print, &a);
b.execFunction();
return 0;
}
I don't really like this solution. A better solution would be that class B could have a function where it returns a bool when the function needs to be executed. This way you could simply place an if statement in the main-function that executes the desired function.
A a(5);
B b;
while (;;) {
if (b.aTest())
a.print();
}
Where B::aTest() is declared as
bool B::aTest();
Hope this helps anyone that comes across the same problem. So it is perfectly possible but pretty dodgy in my opinion, and I don't encourage people using the first method.

Converting method signatures

typedef void (__thiscall* LPVOIDPROC) (void);
class ClassA
{
LPVOIDPROC m_pProc;
void SetProc(LPVOIDPROC pProc) { m_pProc = pProc; }
void OnSomeEvent() { m_pProc(); }
}
class ClassB
{
ClassA* pCA;
void Proc() { /* ... */ }
void Init()
{
// Assume pCA != NULL
pCA->Set((LPVOIDPROC)&ClassB::Proc); // error C2440
}
}
How to get rid of this error C2440: 'type cast' : cannot convert from 'void (__thiscall ClassB::* )(void)' to 'LPVOIDPROC' ? I don't want to limit LPVOIDPROC signature to ClassB only. This should be any class and referenced proc should not be static.
Workaround:
typedef void (* CLASSPROC) (void *);
template<class T, void (T::*proc)()>
void class_proc(void * ptr)
{
(static_cast<T*>(ptr)->*proc)();
}
class ClassA
{
CLASSPROC m_pProc;
void * m_pInstance;
public:
void SetProc(void *pInstance, CLASSPROC pProc) {
m_pInstance = pInstance;
m_pProc = pProc;
}
void OnSomeEvent() { m_pProc(m_pInstance); }
};
class ClassB
{
ClassA* pCA;
void Proc() { /* ... */ }
void Init()
{
// Assume pCA != NULL
pCA->SetProc(this, class_proc<ClassB, &ClassB::Proc>);
}
};
I refer you to this link. Your type LPVOIDPROC is a pointer-to-function, which is not the same thing as a pointer-to-member-function. When you try to cast ClassB::Proc, you are trying to convert a pointer-to-member-function, an invalid operation.
You should take a look at boost::function, that offers exactly what you are looking for. Or you could use functors to encapsulate your functions if you don't want to resort to boost. Example:
struct VoidProcFunctor {
virtual void call() = 0;
};
class ClassB;
struct BProcFunctor : VoidProcFunctor {
BProcFunctor(ClassB* b) : b_(b) {}
void call();
private:
ClassB* b_;
}
class ClassA
{
public:
VoidProcFunctor* m_pProc;
void SetProc(VoidProcFunctor* pProc) { m_pProc = pProc; }
void OnSomeEvent() { m_pProc->call(); }
};
class ClassB
{
ClassA* pCA;
void Proc() { /* ... */ }
void Init()
{
// Assume pCA != NULL
// warning! this is not the best design possible
BProcFunctor* bproc = new BProcFunctor(this);
pCA->SetProc(bproc);
}
};
void BProcFunctor::call() { b_->proc() }
Non-static methods require a 'this' pointer, without a 'this' pointer you cannot call it, and so it makes no sense to cast it to a C function pointer.
Consider making a simple class (let's call it X) that has
a data member that refers to a ClassB instance
a () operator (although I prefer methods with clear names) calling ClassB::Proc using the ClassB instance as this-pointer.
Instead of passing a function pointer to class A, make an instance of X (with its datamember to ClassB filled in) and pass this to class A.
Instead of calling a function pointer class A should call x().
Class X could even be written using templates, so if you have this situation for more than one class you must only write it once.
I think that in C# it can be done cleaner using delegates but I leave that to the C# and .Net specialists.
Never cast function pointers. You can end up with stack corruption. Don't do it.
Don't pass pointers to non-static member functions. They use a different calling convention and are not compatible.
In your case, making "Proc()" static might solve the problem.
You need your Proc method to be a static method.