Octopull/C++: Compile Time Indirection
Home C++ articles Java articles Agile articles Bridge lessons

Compile Time Indirection - An Unusual Template Technique - by 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 impementation 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. (A 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 inacessibility isssue. 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 {
    public:
        /* 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.


Copyright © 2001 Alan Griffiths