Yes, you can. But you can specify each default template argument only once.
17.1/14
The set of default template-arguments available for use is obtained by merging the default arguments from all prior declarations of the template in the same way default function arguments are (dcl.fct.default).
[ Example:
template<class T1, class T2 = int> class A;
template<class T1 = int, class T2> class A;
is equivalent to
template<class T1 = int, class T2 = int> class A;
— end example ]
And 17.1/16
A template-parameter shall not be given default arguments by two different declarations in the same scope. [ Example:
template<class T = int> class X;
template<class T = int> class X { /* ... */ }; // error
— end example ]
( Note, these are taken from the latest draft, but these rules haven't changed in recent years to my knowledge )
If you want to be able to make use of the default arguments when only the declaration is know, you'd have to define them in the declaration. Above also answers the question that you asked in the comments:
I feel like this gets really nasty really quick. What if I include 2 separate headers that include different defaults in their forward declarations? Or is that what you're addressing?
If you did that your program would be ill-formed, as you are allowed to specify each default argument only once. Having two declarations, where one defines the default arguments and the other doesn't, does not really cause any problems because they are not in disagreement of eachother. It only means that if only the version without defaults is known, you'd have to specify all arguments when instantiating your template.
My personal opinion would be to have only one declaration in a header that specifies the default template arguments, and then include that header wherever you need the declaration (and for the definition as well).