Department of Engineering

IT Services

C++ mem_fun

How to use mem_fun

Look at this code

   #include <iostream>
   #include <vector>

   using namespace std;

   class Element {
   public:
     void print() { cout << "Element's print function\n";}
   };

   int main() {
     Element e1,e2,e3;
     vector<Element*> E;
     E.push_back(&e1);
     E.push_back(&e2);
     E.push_back(&e3);

     for (int j=0;j<E.size();j++)
         E[j]->print();
   }

It creates a new simple class, creates three objects of that class, then puts pointers to these objects into a vector. The for loop calls the print function of each object. The code works, but before long you'll want to use the standard library's "algorithms" so you'll need to become familiar with iterators (they point to particular elements within vectors, etc). Each type of container (a vector is a container, so is a list, etc) has associated iterator types. If we wanted to create an iterator to point to successive elements in our vector it would need to be of type vector<Element*>::iterator, which is a struggle, but at least

     for (vector<Element*>::iterator i=E.begin();i<E.end();i++)
         (*i)->print();

works as a replacement for the initial for loop. Fortunately the standard library contains a for_each command to make things easier (it saves us having to create the iterator explicitly). But if we try

     for_each (E.begin(),E.end(), &Element::print);

(or some minor variation of it) the compiler will complain, because for_each requires a global function. One solution is to provide such a function as follows

     void do_print(Element *e) {
         e->print();
     }
     ...
     for_each (E.begin(),E.end(), do_print);

but this is inelegant. Here's where mem_fun comes in useful. This adapter lets you use member functions where a global function is called for. It creates a Function object and is easy to use

     for_each (E.begin(),E.end(), mem_fun(&Element::print));

Details

mem_fun is one of a family of routines that include mem_fun1, mem_fun_ref, and mem_fun_ref1. These adaptors are useful if you want to combine generic programming with inheritance and polymorphism.

The class's constructor takes a pointer to a member function, and provides an operator() that forwards the call to that member function. In this way the resulting object serves as a global function object for that member function. The accompanying function template simplifies the use of this facility by constructing an instance of the class on the fly. The library provides zero and one argument adaptors for containers of pointers and containers of references. Use mem_fun_ref if the container holds objects, so that for_each operates on references to those objects, and use mem_fun if (as above) the container holds pointers to objects.

The result of calling mem_fun is a function object that takes a pointer to the element as its first argument. The result of calling mem_fun_ref is a function object that takes a reference to the element as its first argument. The first argument is used as the this value in the resulting member function call. If the member function takes an argument, it is passed as the second argument to the function object.

An example

#include <iostream>
#include <vector>
#include <functional>

using namespace std;

class Shape {
public:
  virtual void draw(){cout << "Drawing a shape\n"; };
};


class Triangle : public Shape {
  void draw() {cout << "Drawing a triangle\n"; }
};

class Square : public Shape {
  void draw() {cout << "Drawing a square\n"; }
};

int main() {
  vector<Shape*> shapes;
  Triangle t1,t2;
  Square s1, s2;
  shapes.push_back(&t1);
  shapes.push_back(&s1);
  shapes.push_back(&t2);
  shapes.push_back(&s2);
 
  for_each( shapes.begin(),  shapes.end(), mem_fun(&Shape::draw)); 
}