Default template parameters with forward declaration

Viewed 11667

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.

4 Answers

I don't think you can forward declare a template with default arguments unless the library in question provided its own forward declaration header. This is because you can't respecify the default arguments (even if they match... gcc will still report “error: redefinition of default argument”).

So to the best of my knowledge the solution is for the library to supply a forward declaration header Foo_fwd.h:

#ifndef INCLUDED_Foo_fwd_h_
#define INCLUDED_Foo_fwd_h_
template<class T, class U=char> class Foo; // default U=char up here
#endif

and then the full implementation in Foo.h would be:

#ifndef INCLUDED_Foo_h_
#define INCLUDED_Foo_h_
#include "Foo_fwd.h"
template<class T, class U> class Foo { /*...*/ }; // note no U=char here
#endif

So now your code could use Foo_fwd.h as well... but unfortunately, since this approach requires modifying the original Foo.h to remove the default arguments this doesn't scale to 3rd party libraries. Maybe we should lobby the C++0x crew to allow equivalent respecification of default template arguments, à la typedefs...?

Related