Bruce Eckel's Thinking in C++, 2nd Ed Contents | Prev | Next

Member function templates

It’s also possible to make apply( ) a member function template of the class. That is, a separate template definition from the class’ template, and yet a member of the class. This may produce a cleaner syntax:

dogs.apply(&Gromit::sit);

This is analogous to the act (in Chapter XX) of bringing ordinary functions inside a class. [59]

The definition of the apply( ) functions turn out to be cleaner, as well, because they are members of the container. To accomplish this, a new container is inherited from one of the existing STL sequence containers and the member function templates are added to the new type. However, for maximum flexibility we’d like to be able to use any of the STL sequence containers, and for this to work a template-template must be used, to tell the compiler that a template argument is actually a template, itself, and can thus take a type argument and be instantiated. Here is what it looks like after bringing the apply( ) functions into the new type as member functions:

//: C19:applyMember.h
// applySequence.h modified to use 
// member function templates

template<class T, template<typename> class Seq>
class SequenceWithApply : public Seq<T*> {
public:
  // 0 arguments, any type of return value:
  template<class R>
  void apply(R (T::*f)()) {
    iterator it = begin();
    while(it != end()) {
      ((*it)->*f)();
      it++;
    }
  }
  // 1 argument, any type of return value:
  template<class R, class A>
  void apply(R(T::*f)(A), A a) {
    iterator it = begin();
    while(it != end()) {
      ((*it)->*f)(a);
      it++;
    }
  }
  // 2 arguments, any type of return value:
  template<class R, class A1, class A2>
  void apply(R(T::*f)(A1, A2), 
    A1 a1, A2 a2) {
    iterator it = begin();
    while(it != end()) {
      ((*it)->*f)(a1, a2);
      it++;
    }
  }
}; ///:~

Because they are members, the apply( ) functions don’t need as many arguments, and the iterator class doesn’t need to be qualified. Also, begin( ) and end( ) are now member functions of the new type and so look cleaner as well. However, the basic code is still the same.

You can see how the function calls are also simpler for the client programmer:

//: C19:applyGromit2.cpp
// Test applyMember.h
#include "Gromit.h"
#include "applyMember.h"
#include <vector>
#include <iostream>
using namespace std;

int main() {
  SequenceWithApply<Gromit, vector> dogs;
  for(int i = 0; i < 5; i++)
    dogs.push_back(new Gromit(i));
  dogs.apply(&Gromit::speak, 1);
  dogs.apply(&Gromit::eat, 2.0f);
  dogs.apply(&Gromit::sleep, 'z', 3.0);
  dogs.apply(&Gromit::sit);
} ///:~

Conceptually, it reads more sensibly to say that you’re calling apply( ) for the dogs container.

Why virtual member template functions are disallowed

Nested template classes


[59] Check your compiler version information to see if it supports member function templates.

Contents | Prev | Next


Contact: webmaster@codeguru.com
CodeGuru - the website for developers.
[an error occurred while processing this directive]