passing function pointer to a function

Hi:

I want a function that takes a function pointer so that I can feed it with whatever function (that I find suitable and that have different parameters) when I call it. Is this possible? I looked up about passing function pointer to a function. But it looks like then the arguments of the passed function have to be fixed.

Please help. Thanks.
sdc248Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Maen Abu-TabanjehNetwork Administrator, Network ConsultantCommented:
here is what i found :
.H file :

#ifndef MyTree_h
#define MyTree_h
#include ".\node.hpp" // data storage

class BinaryTree
{
public:
	BinaryTree(void);
	~BinaryTree(void);
	
	int CreateNode(void);	
	void PrintList(void);	
	int Search(int, Node*);	
	int InsertNode(Node* sentNode);	
	int ResortTree(void);// not implemented yet

private:
	Node* Root;
	//  For general use for the methods of this class
	Node* currentPointer;

	int RecursiveDataPrint(Node* sentPtr,void(*sent)(Node *));
	int totalNodeCount;	
	void PrintNodeData(Node *sentNode);
};
#endif

Open in new window


.cpp :

#include ".\binarytree.hpp"
#include<iostream>
//#include<string>
using namespace std;

BinaryTree::BinaryTree(void)
: Root(0)
, currentPointer(NULL)
, totalNodeCount(0)
{
}// EO Constructor


BinaryTree::~BinaryTree(void)
{
}
// *************************************************
//             CreateNode Method
// *************************************************
int BinaryTree::CreateNode()
{
	
	int iResult = ERROR;
	Node* objAddedNode = new Node(); // <strong class="highlight">a</strong> temporary node is created
	
	iResult = InsertNode(objAddedNode);
	delete objAddedNode;
	
	return iResult;
}// EOF   CreateNode

// *************************************************
// PrintList Method
// *************************************************
void BinaryTree::PrintList(void)
{
	if (Root == 0)
		cout << " The tree is Empty " << endl;
	else{
        RecursiveDataPrint(Root,PrintNodeData);
		//Root->PrintAgentData();
		//RecursiveDataPrint(Root->GetRightNodePtr());
	}
            	
}// EOF  PrintList

// *************************************************
//		RecursiveDataPrint
// *************************************************
int BinaryTree::RecursiveDataPrint(Node* sentPtr, void(*sent)(Node &))
{
	//int iResult = ERROR;
	
	if (sentPtr->GetLeftNodePtr() == 0 && sentPtr->GetRightNodePtr() ==0)		
			(*sent)(sentPtr);
		//sentPtr->PrintAgentData();
	else{
		if(sentPtr->GetLeftNodePtr() != 0)
			RecursiveDataPrint(sentPtr->GetLeftNodePtr(),sent);
		(*sent)(sentPtr);
		//sentPtr->PrintAgentData();
		if (sentPtr->GetRightNodePtr() != 0) 			
            RecursiveDataPrint(sentPtr->GetRightNodePtr(),sent);		
	}
	return 0;
}// EOF RecursiveDataPrint

// *************************************************
//		Search Method
// *************************************************
int BinaryTree::Search(int searchData, Node* sentNode)
{
	int iResult = ERROR;
	if(Root == 0)
		iResult = EMPTY;
	else
	{
		bool bEndSearch = false;

		currentPointer = Root;

		while(currentPointer != 0 && !bEndSearch){
			if(currentPointer->GetAgentNumber() == searchData){
				// found the data
				bEndSearch = true;
				sentNode->SetAgentName(currentPointer->GetAgentName());
				sentNode->SetAgentNumber(currentPointer->GetAgentNumber());
			}
			if(currentPointer->GetAgentNumber() < searchData)
				currentPointer = currentPointer->GetRightNodePtr();
			else
				currentPointer = currentPointer->GetLeftNodePtr();

		}
		if (bEndSearch)
			iResult = SUCCESS;
	}    
	return iResult;
}// EOF  Search

// *************************************************
//		InsertNode Method
// *************************************************
int BinaryTree::InsertNode(Node* sentNode)
{
	// Traverse the tree looking for the position.  
	//If <strong class="highlight">a</strong> node exists with same data return error.
	// If not insert node and set pointers.
	// increment total count// <strong class="highlight">to</strong> be added.
	int iResult = ERROR;
	Node*  objNewNode = new Node(1);
	objNewNode->SetAgentName(sentNode->GetAgentName());
	objNewNode->SetAgentNumber(sentNode->GetAgentNumber());
	
	if (Root == 0){
		Root = objNewNode;
		iResult = SUCCESS;
	}
	else{
		Node* trailerPointer;
		bool bDirection = true; // I have true = left, false = right..
		currentPointer = Root;
		while( currentPointer != 0 && iResult != OVERFLOW )
		{// continue search
			trailerPointer = currentPointer; // trailer <strong class="highlight">pointer</strong> <strong class="highlight">to</strong> the parent
			if(sentNode->GetAgentNumber() < currentPointer->GetAgentNumber())
			{// Go left
				bDirection = true;
				currentPointer = currentPointer->GetLeftNodePtr();
			}
			else if (sentNode->GetAgentNumber() > currentPointer->GetAgentNumber())
			{// go right
				bDirection = false;
				currentPointer = currentPointer->GetRightNodePtr();
			}
			else
				iResult = OVERFLOW ;

		}
		if (iResult != OVERFLOW){
			if(bDirection)
                trailerPointer->SetLeftNodePtr(objNewNode);
			else
				trailerPointer->SetRightNodePtr(objNewNode);

			iResult = SUCCESS;
			totalNodeCount++;// increment node count // <strong class="highlight">to</strong> be added

		}
		else
			iResult = ERROR; // this indicates <strong class="highlight">a</strong> matching data value found.`

	}

	return iResult;
}// EOF  InsertNode

// ResortTree  Method
int BinaryTree::ResortTree(void)
{
	//move data from tree <strong class="highlight">to</strong> array.
	// clear all nodes from tree.
	// Reinsert nodes via binary retreival from array.
	Node storageArray[totalNodeCount];

	return 0;
}

// PrintNodeData method
void BinaryTree::PrintNodeData(Node *sentNode)
{
	sentPtr->PrintAgentData();
}

Open in new window

0
Kent OlsenData Warehouse Architect / DBACommented:
Hi scd,

That's a dangerous and very confusing way to program.  But there are several ways around this.

1.  Create a "go between" function that conforms to the parameter list required by the function pointer.  This function will then call your intended function with the correct parameter list.

2.  Pass a class or struct to the function that contains all of the parameters.


Personally, I'd go with option 1.  It's very easy to implement.


Good Luck,
Kent
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
ravenplCommented:
I'm using the boost::function boost::bind pair to achieve this. http://www.codeproject.com/KB/library/BoostBindFunction.aspx
0
Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

lomo74Commented:
or you can use varargs.
something like the following:
 
#include <stdio.h>
#include <stdargs.h>

typedef void (*FUNCPTR)(va_list);

void call_the_func(FUNCPTR the_func, ...)
{
	//call an arbitrary function with arbitrary data
	va_list args;
	va_start(args, the_func);
	the_func(args);
	va_end(args);
}

void print_something(va_list args)
{
	//strip off format from parameters
	char *format = va_arg(args, char*);
	//do print
	vprintf(format, args);
}

int main(void)
{
	call_the_func(print_something, "%s\n", "something to print.");
	return 0;
}

Open in new window

be careful, this way you must take care of the number and type of parameters you feed to the "arbitrary" function.
the compiler won't help you anymore in checking that the parameters you feed are those that the function expects.
0
lomo74Commented:
a more dramatic example
 
#include <stdio.h>
#include <stdargs.h>

typedef void (*FUNCPTR)(va_list);

void call_the_func(FUNCPTR the_func, ...)
{
	//call an arbitrary function with arbitrary data
	va_list args;
	va_start(args, the_func);
	the_func(args);
	va_end(args);
}

void calc_sum(va_list args)
{
	int a = va_arg(args, int);
	int b = va_arg(args, int);
	int *result = va_arg(args, int*);
	*result = a + b;
}

void print_something(va_list args)
{
	//strip off format from parameters
	char *format = va_arg(args, char*);
	//do print
	vprintf(format, args);
}

int main(void)
{
	int a = 4, b = 7, n;
	call_the_func(calc_sum, a, b, &n);
	call_the_func(print_something, "the sum of %i + %i is %i\n", a, b, n);
	call_the_func(print_something, "%s\n", "something to print.");
	return 0;
}

Open in new window

0
evilrixSenior Software Engineer (Avast)Commented:
>> I want a function that takes a function pointer
If you're using C++ you can do this very simply by using templates (and simpler by using functors). There's no need to use var args since you can bind whatever function you want to call using a function object (as ravenpl points you can use boost bind to perform the binding but you don't need to if you are not using boost; you can implement the binding yourself).

http://www.newty.de/fpt/functor.html#chapter4

template <typename funcT>
void foo(funcT func)
{
      func();
}

struct myFunctor
{
   void operator()()
   {
   }
};

myFunctor f;
foo(f);

Open in new window


As for being able to handle different function prototypes; a function is just a class with over-loaded function operators and you can implement as many of these are you like in one function. Just like with all other function overloading the correct one will be called depending upon the parameter list passed to the functor when you call it.
0
eagerCommented:
You can use varargs to pass different parameter lists to the function, but it doesn't make much sense to me.  The calling function is fixed: it can only pass a defined set of parameters to the function passed as an argument.

You might look at the visitor design pattern:  http://en.wikipedia.org/wiki/Visitor_pattern

I also recommend using functors as @evilrix mentions.
0
sdc248Author Commented:
Thanks, guys. I've resolved the problem with kdo's suggestion, ie. pass an object of a struct as the called function's aurgement. It happens that the candidate functions to be called, although are in different nature and require different arguments, these arguments are all members of same struct.

The other suggestions would probably work too. But I am going for kdo's solution for now because it's the easiest for my case.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.