ACCU Home page ACCU Conference Page ACCU 2017 Conference Registration Page
Search Contact us ACCU at Flickr ACCU at GitHib ACCU at Google+ ACCU at Facebook ACCU at Linked-in ACCU at Twitter Skip Navigation

pinCompile Time Indirection - An Unusual Template Technique

Overload Journal #42 - Apr 2001 + Programming Topics   Author: Alan Griffiths

It is a common idiom in C++ to write a class whose sole data member is a pointer to another class that provides the implementation. Originally called "The Cheshire Cat Idiom" this has more recently been dubbed "Compilation Firewall" and "The Pimpl Idiom". This last comes from the following paradigm:

// Header file
class interface {
  /* omitted */
private:
  class impl;
  impl* pimpl;  
} ;
// Implementation file
class interface::impl {
  /* omitted */
} ;

However, this is all by way on a preamble - since the situation I want to address is motivated less by implementation hiding and more by the desire to provide a variable implementation. For example. we may want to vary between implementations state1, state2 and state3 at run time. (As the names suggest this is one reasonable way to implement state machines.)

The only difficulty with this is that we can't write:

class state1 : public interface::impl {
...

because interface::impl is inaccessible.

There are two obvious approaches to resolving this inaccessibility issue. Both of these are inelegant because implementation details become exposed in the header file.

The first solution is to make impl a public member of interface. Making impl public pollutes the client interface:

// Header file
class interface {
  /* omitted */
  class impl;
private:
  impl* pimpl;  
} ;
// Implementation file
class interface::impl {
  /* omitted */
} ;
// . . .
class state1 : public interface::impl {
  /* omitted */
} ;

The second approach is to forward declare state1 (and kin) and make them friends. This exposes even more of the implementation details in the header file:

// Header file
class state1;
class interface {
  /* omitted */
private:
  friend state1;
  class impl;
  impl* pimpl;  
} ;
// Implementation file
class interface::impl {
  /* omitted */
} ;
// . . .
class state1 : public interface::impl {
  /* omitted */
} ;

Neither approach is a disaster, but the inelegance niggled at me until I realised there was a third solution that retains the original form of the header file:

// Header file
class interface {
  /* omitted */
private:
  class impl;
  impl* pimpl;  
} ;
// Implementation file
class interface::impl {
  /* omitted */
} ;
// . . .
template<class impl>
class state1 : public impl {
/* omitted */
} ;
// . . .
interface::interface(): pimpl(new state1<impl>)
// . . .

This works because interface has access to impl and can use it as a template parameter and because state1<> has access to its template parameter.

In C++ the template mechanisms are most commonly used to support genericity. The technique illustrated here is unusual in that it uses them instead to promote encapsulation.

Overload Journal #42 - Apr 2001 + Programming Topics