less than 1 minute read

If you’re not familiar with the PImpl (private implementation) idiom, read this Wikipedia article first. While this is more or less “syntactic sugar” since the templates are expanded during compilation, but I think it makes for cleaner looking code.

Classic PImpl

Usually, while forward declaring the pimpl struct or class, we do something like this:

class MyClass
{
  struct Implementation;
  MyClass::Implementation* pimpl;

public:
  MyClass();
  ~MyClass();

  void DoAllTheThings();
};

And the following definition:

#include "MyClass.h"

struct MyClass::Implementation
{
  int foo;
  int bar;
}

PImpl<T>

There’s absolutely nothing wrong with that, but consider the following reusable template:

template<typename T>
struct PImpl
{
protected:
  struct Implementation;
  Implementation* pimpl;
};

And the following implementation of the template:

#include "PImpl.h"

class MyClass :
  public PImpl<MyClass>
{
public:
  MyClass();
  ~MyClass();

  void DoAllTheThings();
};

And the following source file definition:

#include "MyClass.h"

template<>
struct PImpl<MyClass>::Implementation
{
  int foo;
  int bar;
};

There is no forward declaration of the struct in MyClass, only public inheritance of Pimpl<T> and the implementation in the source file is nearly identical.