C++ Templated Namespaces

A neat trick you can do with templating is to create a templated namespace – i.e., a module/namespace that is bound at compile time rather than design time. The interesting uses of these things come not from creating them, as they’re trivial (mostly a typedef), but rather any class expecting one as one of it’s template parameters. It opens up what might be called “Context Oriented Programming” – a kind of aspect-orientation, monkey patching and structural typing package all wrapped up in one.

With the coming of C++0x concepts, this type of templating will become much easier. We will no longer have to define our classes in terms of what libraries they require, but instead what types they require, and any and all dependencies will more or less go the way of the dinosaur in truly generic programming.

For example, here’s the templated namespace idiom:

template<class IntType, class FloatType, class ThreadType, class MemoryModelType>

struct TemplatedNamespace {

typedef IntType MyIntType;

typedef FloatType MyFloatType;

typedef ThreadType MyThreadtype;

typedef MemoryModelType MyMemorymodelType;

};

Pretty trivial. Now, it’s use:

template<class ANamespace>

class UserClass {

ANamespace::MyIntType foo(ANamspace::MyIntType x){

ANamespace::MyThreadType::lock _lock();

return 2 + x;

}

};

A little wordy, but as you can see, we just wrote a class that doesn’t know what threading model it’s using, doesn’t know what type of int it’s using, or anything else. Then, when we want to use this class, we build the namespace we want to use…

typedef TemplatedNamespace<long long, double, PTHREAD, NEW_DELETE> myNamespace;

UserClass<myNamespace> x;

We bind what threading we want as the user, rather than the designer having to try and think how to accommodate us no mater what. This is similar to policy-driven-development on steroids, as you can begin to remove any and all types from your code and move them up to requirements on your ‘context’, or some passed in templated namespace. These requirements can be expressed and checked at compile time via the use of C++0x’s concepts.

As you can see, since a class only drawing types from it’s ‘context’ rather than from any global types, we, the user, have very strict control over it. We can pass in mock types a la dependency injection, as long as we meet the requirements as spelled out in any concepts the class uses. We can also muck around AOP style with types that the original designer never meant to be overloaded or switched out. Again, as long as we meet the concepts, the class should work (your mileage may vary).

Making a non-thread safe class into a threadsafe one simply replaces the various types that there should be threadsafe versions of. Now a class doesn’t even know it’s threadsafe, but it is. Similar to Python’s monkey patching (or duck punching), simply having types that meet the structural typing demands of concepts will work, meaning maintaining code can be as simple as switching out different types rather than going in and finding all the hidden dependencies that must now be changed.

Plus, it gives you a very refreshing feeling looking up at the top of your class and not seeing a single #include there.

Obviously this approach is wordy as hell, and like everything in C++, we feel like we’re fighting the system to do what we want. But this approach also affords us a great deal of extensibility, maintainability and generic power to reuse different classes and code by simply changing the ‘context’, or namespace, it uses to find all of it’s types. And with the upcoming C++0x concepts, it will aid in design because it will force us to think about our bare assumptions of what we expect our types to do, much like classic Design-By-Contract forces us to think about what our instantiations of those types might do.

I have a feeling we’ll all be seeing more and more of this type of truly generic programming 😉