Проблема не связана с параметром шаблона по умолчанию. Вместо этого тип p
(std::shared_ptr<B<int, int>>
) не может быть сопоставлен с аргументом std::shared_ptr<T>
шаблона foo
: при выводе аргумента шаблона не учитываются преобразования и передается ссылка на производное Экземпляр класса в качестве ссылки на базовый класс действительно является преобразованием.
Вы можете решить проблему, явно переместив указатель, которым управляет std::shared_ptr
.
std::shared_ptr<A<int>> p = std::make_shared<B<int, int>>();
Теперь эти вызовы будут работать, как и ожидалось:
foo<>(p); // Ok, argument matches the signature
foo(p); // Same...
Обратите внимание, что имеет большое значение, появляется ли тип аргумента шаблона в списке параметров шаблона функции (делает возможным вывод) или нет. Рассмотрим эти два шаблона,
template <class T = int> void foo(T&&)
{
std::cout << __PRETTY_FUNCTION__ << "\n";
}
template <class T = int> void bar(double)
{
std::cout << __PRETTY_FUNCTION__ << "\n";
}
Оба имеют тип по умолчанию int
, но когда они создаются, как это
foo<>(0.0); // outputs: void foo(T&&) [with T = double]
bar<>(0.0); // outputs: void bar(double) [with T = int]
первый экземпляр использует аргумент функции для вывода параметра шаблона (в результате double
), в то время как второй ничего не выводит и по умолчанию равен int
.