Wednesday, November 7, 2007

C++ : default template parameters

Assume you have a templated class, and some template parameters have default values. What if you want to specify only some parameters, and leave some to their defaults?

The problem is that you need to specify all parameters until the last you want to change.

class f_base = formatter::base,
class d_base = destination::base,
class f_ptr = f_base*,
class d_ptr = d_base*>
struct logger { ... }

If you want to specify d_ptr, you'll have to specify f_base, d_base and d_ptr as well:
logger<formatter::base,destination::base,my_ptr> l;

The more complicated the params are, the more complicated the client code will look. And by the way, what if the defaults change?

There's an easy solution: use a default_ class:

struct default_ {};
template<class param, class default_type> struct use_default
{ typedef param type; };

template<class default_type> struct use_default <default_, default_type>
{ typedef default_type type; };

Now, the client code will look a lot simpler:

logger <default_,default_,default_,my_ptr> l;

In your class, you'll do something like this:

class f_base = default_,
class d_base = default_,
class f_ptr = default_,
class d_ptr = default_>
struct logger {
typedef use_default <f_base, formatter::base> ::type formatter_type;
typedef use_default <d_base, destination::base> ::type destination_type;
typedef use_default <f_ptr, formatter_type*> f_ptr_type;
typedef use_default <d_ptr, destination_type*> d_ptr_type;

Your users will be waaay happier with this interface - especially if you use it across multiple templated classes. All they will need to remember is which parameters to set, while forgetting the rest.

As a side-note, I've used this in the Boost Logging Lib v2.

1 comment:

David Rodríguez said...

Nice small little trick with default_