Default template parameters with forward declaration

Seth Johnson picture Seth Johnson · Nov 24, 2009 · Viewed 10.3k times · Source

Is it possible to forward declare a class that uses default arguments without specifying or knowing those arguments?

For example, I would like to declare a boost::ptr_list< TYPE > in a Traits class without dragging the entire Boost library into every file that includes the traits. I would like to declare namespace boost { template<class T> class ptr_list< T >; }, but that doesn't work because it doesn't exactly match the true class declaration:

template < class T,
    class CloneAllocator = heap_clone_allocator,
    class Allocator = std::allocator<void*>
    >
class ptr_list { ... };

Are my options only to live with it or to specify boost::ptr_list< TYPE, boost::heap_clone_allocator, std::allocator<void*> in my traits class? (If I use the latter, I'll also have to forward declare boost::heap_clone_allocator and include <memory>, I suppose.)

I've looked through Stroustrup's book, SO, and the rest of the internet and haven't found a solution. Usually people are concerned about not including STL, and the solution is "just include the STL headers." However, Boost is a much more massive and compiler-intensive library, so I'd prefer to leave it out unless I absolutely have to.

Answer

Potatoswatter picture Potatoswatter · Apr 28, 2010

Yes. Default template arguments may be specified any time, anywhere, so long as the declarations don't conflict with each other. They are ultimately merged together from the various declarations.

Even this is legal:

template< class A, class B, class C = long >
class X;

template< class A, class B = int, class C >
class X;

template< class A = short, class B, class C >
class X { };

A similar example is given in §14.1/10. According to that paragraph, function default arguments behave similarly.

Good luck on getting the forward declaration to behave itself and not barf on everything!