Сбой вывода шаблона для полиморфного класса с параметрами шаблона по умолчанию - PullRequest
0 голосов
/ 06 ноября 2018

Рассмотрим этот пример:

#include <memory>

template<typename T>
class A {};

template<typename T1, typename T2>
class B: public A<T1> {};

template<typename T = int>
void foo(std::shared_ptr< A<T> > test)
{

}

int main()
{
    auto p = std::make_shared<B<int, int>>();
    foo<int>(p);    // Works
    foo<>(p);       // Does not work
    foo(p);         // Does not work
}

Я пытаюсь заставить это скомпилироваться без явного указания типа T для foo, но это не работает. Я не уверен, почему, как будто я явно использую тип T, он работает просто отлично, но если я это сделаю, он не скомпилируется, хотя я сказал компилятору, каким должен быть тип T, если я этого не сделаю явно указать его.

Я понимаю, почему компилятор не может определить тип T, но почему он не может использовать мой тип T по умолчанию, когда я его не указываю? Как мне обойти это и как это «правильно» сделать это?

1 Ответ

0 голосов
/ 06 ноября 2018

Проблема не связана с параметром шаблона по умолчанию. Вместо этого тип 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...