Question

This is the provided function template I'm trying to use:

template <class Process, class BTNode>
void postorder(Process f, BTNode* node_ptr)
{
   if (node_ptr != 0)
   {
      postorder( f, node_ptr->left() );
      postorder( f, node_ptr->right() );
      f( node_ptr->data() );
   }
}

This is my call, and the function I'm passing:

void city_db::print_bst() {
   postorder(&city_db::print, head);
}

void city_db::print(city_record target)
{
   std::cout << target.get_code();
}

This is the compile time (G++) error I get:

CityDb.cpp:85: instantiated from here

BinTree.template:80: error: must use ‘.’ or ‘->’ to call pointer-to-member function in ‘f (...)’

make: *** [CityDb.o] Error 1

This is in reference to the line f( node_ptr->data() ); in the function template.

This is for a Data Structures project. The assignment was modified so we don't need to pass a function to a function, but I've been interested in this for quite some time, and I feel like I almost have it here. I've exhausted Google and Lab TA's, so if StackOverflow has ideas, they would be greatly appreciated.

Was it helpful?

Solution

Your problem is that postorder accepts a function object that must be called this way:

f(arg);

You are passing in a pointer to member function. You should first call mem_fun to make a function object from the pointer to member:

std::mem_fun(&city_db::print)

The returned function object takes two arguments: the pointer to a city_db (the implicit this pointer), and the object to be printed. You can bind the first to this with bind1st, like this:

std::bind1st(std::mem_fun(&city_db::print), this)

And now you should be able to call postorder on it:

postorder(std::bind1st(std::mem_fun(&city_db::print), this), head);

OTHER TIPS

You need an instance of city_db to call print on.

What you're passing is a pointer to a member function (think of it as a slot in the vtable), but you need a this pointer too. You could pass this in as another argument to the postorder function.

template <class Object, class Process, class BTNode>
void postorder(Object* obj, Process f, BTNode* node_ptr)
{
   if (node_ptr != 0)
   {
      postorder(obj, f, node_ptr->left() );
      postorder(obj, f, node_ptr->right() );
      ((obj)->*(f))( node_ptr->data() );
   }
}

See C++ FAQ Lite

You need to either make city_db::print() static or provide a city _db object.

As written

void city_db::print(city_record target)
{
   std::cout << target.get_code();
}

Does not depend on the class state. Declare it as a static function and compiler will not need this pointer to call it. FAQ on the topic.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top