User Name
Password

Go Back   Planetarion Forums > Non Planetarion Discussions > Programming and Discussion

Reply
Thread Tools Display Modes
Unread 19 Apr 2005, 12:29   #1
Radical Edward
Registered User
 
Join Date: Feb 2002
Location: South Pacific
Posts: 4,911
Radical Edward needs a job and a girlfriendRadical Edward needs a job and a girlfriendRadical Edward needs a job and a girlfriendRadical Edward needs a job and a girlfriendRadical Edward needs a job and a girlfriendRadical Edward needs a job and a girlfriendRadical Edward needs a job and a girlfriendRadical Edward needs a job and a girlfriendRadical Edward needs a job and a girlfriendRadical Edward needs a job and a girlfriendRadical Edward needs a job and a girlfriend
[c++] writing a member function that returns a pointer to a member function

Hi there. I am trying to write a member function that returns a pointer to a member function (all within the same class). I understand how to return a pointer to a function without too much trouble, but when it is to a member function I get a bit lost. anyway, here is the test code and it won't compile, can you see where it goes wrong?

#include <iostream>

class testfunction
{
public:

testfunction();
int func1(int first);
int func2(int second);
int func3(int third);
int nullfunc(int droppednum);

//returns a pointer to one of the above

int (*getfunc(int whichone))(int);

private:

int myFirst;
int mySecond;
int myThird;
};

testfunction::testfunction()
{
std::cout << "testfunction constructor\n";
myFirst = 1;
mySecond = 2;
myThird = 3;
}

testfunction::func1(int first)
{
std::cout << "first function\n";
return myFirst * first;
}

testfunction::func2(int second)
{
std::cout << "second function\n";
return mySecond * second;
}

testfunction::func3(int third)
{
std::cout << "third function\n";
return myThird * third;
}

testfunction::nullfunc(int droppednum)
{
std::cout << "null function, returning the number you gave me\n";
return droppednum;
}

testfunction::getfunc(int whichone)
{
if (whichone == 1)
{
return &testfunction::func1;
}
else if (whichone == 2)
{
return &testfunction::func2;
}
else if (whichone == 3)
{
return &testfunction::func3;
}
else
{
return &testfunction::nullfunc;
}
}


int main()
{
testfunction spam;
return 0;
}
__________________
I think it's time we blow this scene, get everybody and the stuff together..........

ok 3..... 2..... 1.. let's jam
Radical Edward is offline   Reply With Quote
Unread 19 Apr 2005, 21:56   #2
Structural Integrity
Rawr rawr
 
Structural Integrity's Avatar
 
Join Date: Dec 2000
Location: Upside down
Posts: 5,300
Structural Integrity needs a job and a girlfriendStructural Integrity needs a job and a girlfriendStructural Integrity needs a job and a girlfriendStructural Integrity needs a job and a girlfriendStructural Integrity needs a job and a girlfriendStructural Integrity needs a job and a girlfriendStructural Integrity needs a job and a girlfriendStructural Integrity needs a job and a girlfriendStructural Integrity needs a job and a girlfriendStructural Integrity needs a job and a girlfriendStructural Integrity needs a job and a girlfriend
Re: [c++] writing a member function that returns a pointer to a member function

Look up "functors". They are wrappers that take care for pointers to member functions. I believe the gamedev article "Enginuity, part 2" (or part 3) has an elaborate description on them.

The code below is from my codebase. It's rather old, and has a few quirks to make it compile under VC++ (VC++ doesn't allow partial specialisation in templates which causes all kinds of troubles here).

BTW, If I were to guess what the problem is, it'd be the ampersands before the returning of the function pointer in getfunc().
Plus your functions don't have a return type before your function definitions.
I can't try it out ATM because I haven't installed my compiler on this PC yet.

Code:
/** The Functor object is the parent of the ObjFunctor. 
This because this way we make it possible this way to fill containers with Functors to multiple objecttypes

The virtual functions are meant for easy access and the ability to actually make lists and vectors of functors. The ObjFunctor has more specialised functions.
*/
class Functor
{
public:
	virtual void call()=0;
	virtual void call(int i)=0;	//sometimes one might want to pass a variable to the function. 
	//We limit ourselves to an integer for the sake of simplicity
};

/** This is the ObjFunctor, the heart of our functor. The object holds a templated pointer to an object and can have a certain return type for the function.

Creating an objectFunctor: ObjFunctor<myreturntype, myclass, myreturntype (myclass::*)(param1)> functorname(objectpointer, functionpointer);
Calling a functor: 
functorname(); //no return type, no arguments
functorname.callWithReturn(); //with return type, no arguments
functorname(param1, param2); //with return type and two arguments
*/
template<typename ReturnType, class TClassType, typename funcType>
class ObjFunctor : public Functor
{
protected:
	//typedef ReturnType (TClassType::*funcType)();
	//funcType func;
	funcType func;	//pointer to the function
	//funcType nonparamfunc;
	void (TClassType::*nonparamfunc0)();	//pointer to a function with no parameters used for mass-storage
	void (TClassType::*nonparamfunc1)(int);	//pointer to a function with one parameter used for mass-storage
	TClassType* obj;	//pointer to the actual object

public:

	typedef ReturnType return_type;	//ability to get the return type from the functor

	/** This constructor takes the pointer to the object and the pointer to the function that is going to be called 
	@param o The pointer to the object
	@param f The pointer to the function
	*/
	ObjFunctor(TClassType* o, funcType f)
	{
		obj = o; func = f;
		nonparamfunc0 = 0;
		nonparamfunc1 = 0;
	}

	/** This constructor is supposed to take care of Functors that should be stored in a container
	@param o Pointer to the object we're gonna call
	@param f The pointer to the function
	@param i Integer that indicates how many parameters we are passing through. Can be 0 or 1.
	*/
	ObjFunctor(TClassType* o, funcType f, int i)
	{
		obj = o;
		if (i==0)
		{
			nonparamfunc0 = (void (TClassType::*)())f; //cast the function pointer to a function pointer with no arguments
			nonparamfunc1 = 0;
		}
		else if (i==1)
		{
			nonparamfunc0 = 0;
			nonparamfunc1 = (void (TClassType::*)(int))f; //cast the function pointer to a function pointer with one argument
		}
		else
		{
			nonparamfunc0 = 0;
			nonparamfunc1 = 0;
		}
	}

	/** This function is supposed to allow storage of functors in a container. 
	However there are a few issues regarding this part
	*/
	void call()
	{
		if(nonparamfunc0)	//we should do a check here because I can understand it's very possible to make mistakes here
			(obj->*nonparamfunc0)();
	}

	void call(int i)
	{
		if(nonparamfunc1)	//we should do a check here because I can understand it's very possible to make mistakes here
			(obj->*nonparamfunc1)(i);
	}


	/** The overloaded () operator allows for easy calling of the Functor */
	ReturnType operator ()()
	{
		return (obj->*func)();
	}

	/** The overloaded () operator allows for easy calling of the Functor 
	@param a1 Templated value, can be anything
	*/
	template<typename Arg1>
	ReturnType operator()(Arg1 a1)
	{
			return (obj->*func)(a1);
	}

	/** The overloaded () operator allows for easy calling of the Functor 
	@param a1 Templated value, can be anything
	@param a2 Templated value
	*/
	template<typename Arg1, typename Arg2>
	ReturnType operator()(Arg1 a1, Arg2 a2)
	{
			return (obj->*func)(a1,a2);
	}

	/** The overloaded () operator allows for easy calling of the Functor 
	@param a1 Templated value, can be anything
	@param a2 Templated value
	@param a3 Templated value
	*/
	template<typename Arg1, typename Arg2, typename Arg3>
	ReturnType operator()(Arg1 a1, Arg2 a2, Arg3 a3)
	{
			return (obj->*func)(a1,a2,a3);
	}

	//for more arguments this list has to be expanded to the likeness of the previous overloaded operators
	//
};




template<typename ReturnType, typename funcType>
class GlobalFunctor : public Functor
{
private:
	funcType func; //pointer to the function
	void (*nonparamfunc0)();	//pointer to a function with no parameters used for mass-storage
	void (*nonparamfunc1)(int);	//pointer to a function with one parameter used for mass-storage

public:

	/** This constructor takes the pointer to the function that is going to be called 
	@param f The pointer to the function
	*/
	GlobalFunctor(funcType f)
	{
		func = f;
		nonparamfunc0 = 0;
		nonparamfunc1 = 0;
	}


	/** This constructor is supposed to take care of Functors that should be stored in a container
	@param f The pointer to the function
	@param i Integer that indicates how many parameters we are passing through. Can be 0 or 1.
	*/
	GlobalFunctor(funcType f, int i)
	{
		if (i==0)
		{
			nonparamfunc0 = (void (*)())f; //cast the function pointer to a function pointer with no arguments
			nonparamfunc1 = 0;
		}
		else if (i==1)
		{
			nonparamfunc0 = 0;
			nonparamfunc1 = (void (*)(int))f; //cast the function pointer to a function pointer with one argument
		}
		else
		{
			nonparamfunc0 = 0;
			nonparamfunc1 = 0;
		}
	}



	void call()
	{
		if(nonparamfunc0)	//we should do a check here because I can understand it's very possible to make mistakes here
			(nonparamfunc0)();
	}

	void call(int i)
	{
		if(nonparamfunc1)	//we should do a check here because I can understand it's very possible to make mistakes here
			(nonparamfunc1)(i);
	}


	/** The overloaded () operator allows for easy calling of the Functor */
	ReturnType operator ()()
	{
		return (func)();
	}

	/** The overloaded () operator allows for easy calling of the Functor 
	@param a1 Templated value, can be anything
	*/
	template<typename Arg1>
	ReturnType operator()(Arg1 a1)
	{
			return (func)(a1);
	}

	/** The overloaded () operator allows for easy calling of the Functor 
	@param a1 Templated value, can be anything
	@param a2 Templated value
	*/
	template<typename Arg1, typename Arg2>
	ReturnType operator()(Arg1 a1, Arg2 a2)
	{
			return (func)(a1,a2);
	}

	/** The overloaded () operator allows for easy calling of the Functor 
	@param a1 Templated value, can be anything
	@param a2 Templated value
	@param a3 Templated value
	*/
	template<typename Arg1, typename Arg2, typename Arg3>
	ReturnType operator()(Arg1 a1, Arg2 a2, Arg3 a3)
	{
			return (func)(a1,a2,a3);
	}

	//for more arguments this list has to be expanded to the likeness of the previous overloaded operators
	//
};
__________________
"Yay"
Structural Integrity is offline   Reply With Quote
Unread 20 Apr 2005, 05:08   #3
queball
Ball
 
queball's Avatar
 
Join Date: Oct 2001
Posts: 4,410
queball contributes so much and asks for so littlequeball contributes so much and asks for so littlequeball contributes so much and asks for so littlequeball contributes so much and asks for so littlequeball contributes so much and asks for so littlequeball contributes so much and asks for so littlequeball contributes so much and asks for so littlequeball contributes so much and asks for so littlequeball contributes so much and asks for so littlequeball contributes so much and asks for so littlequeball contributes so much and asks for so little
Re: [c++] writing a member function that returns a pointer to a member function

Quote:
Originally Posted by Structural Integrity
Look up "functors".
That's probably the solution you want. But for God's sake please use STL rather than writing your own <functional>.

Member function pointers would solve the specific problem though:

class testfunction { ... int (testfunction::*getfunc(int whichone))(int); ... };
Then,
int (testfunction::*testfunction::getfunc(int whichone))(int) { ... }

Or use,
class testfunction { ... typedef int (testfunction::*member)(int);
member getfunc(int); ... };
Then,
testfunction::member testfunction::getfunc(int whichone) { }

edit:
and to call:
int (testfunction::*m)(int);
or testfunction::member m;
Then,
m = spam.getfunc(1);
(spam.*m)(10);

Last edited by queball; 20 Apr 2005 at 05:37.
queball is offline   Reply With Quote
Unread 20 Apr 2005, 07:11   #4
Radical Edward
Registered User
 
Join Date: Feb 2002
Location: South Pacific
Posts: 4,911
Radical Edward needs a job and a girlfriendRadical Edward needs a job and a girlfriendRadical Edward needs a job and a girlfriendRadical Edward needs a job and a girlfriendRadical Edward needs a job and a girlfriendRadical Edward needs a job and a girlfriendRadical Edward needs a job and a girlfriendRadical Edward needs a job and a girlfriendRadical Edward needs a job and a girlfriendRadical Edward needs a job and a girlfriendRadical Edward needs a job and a girlfriend
Re: [c++] writing a member function that returns a pointer to a member function

thanks for the help dudes
__________________
I think it's time we blow this scene, get everybody and the stuff together..........

ok 3..... 2..... 1.. let's jam
Radical Edward is offline   Reply With Quote
Reply


Thread Tools
Display Modes

Forum Jump


All times are GMT +1. The time now is 17:18.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Copyright ©2002 - 2018