Проще говоря, предварительное объявление нуждается в параметрах по умолчанию. Просто посмотрите на это так, в упрощенной форме:
template<class T> A;
std::shared_ptr<A<>> a;
Когда компилятор видит это, это вся информация, которую он имеет. Таким образом, в этом случае A<>
явно отсутствует тип для параметров шаблона. Теперь, если вы сделаете:
template<class T = int> A;
std::shared_ptr<A<>> a;
, тогда компилятор может сделать вывод, что A<>
действительно A<int>
.
Вот проблема с этим, хотя. С [temp.param]/12
Параметру шаблона не должны предоставляться аргументы по умолчанию двумя различными объявлениями в одной и той же области видимости.
[ Example:
template<class T = int> class X;
template<class T = int> class X { /* ... */ }; // error
—end example ]
Итак, если вы используете параметр по умолчанию в вашей предварительной декларации, вы не можете использовать его в самом шаблоне. Веселые времена.
Обман, чтобы обойти это, состоит в том, чтобы иметь дополнительный заголовочный файл, который содержит только предварительное объявление шаблона с параметрами по умолчанию, и все файлы, использующие шаблон, включают это вместо полного определения шаблона ( пока не требуется полное определение), включая определение шаблона. Определение шаблона не требует параметров по умолчанию. Не очень весело, но это сработает.
В качестве альтернативы, не пересылать объявление.
См. Примеры здесь