Обе ваши перегрузки являются действительными кандидатами. Если вы удалите любой из них, оставшийся будет по-прежнему допустимой перегрузкой. В таком случае, в широком смысле, будет выбрана перегрузка, которая будет наиболее точно соответствовать предоставленным аргументам.
Вы предоставили std::unique_ptr<Derived>
. В первом случае ожидается std::unique_ptr<Base>
. Существует неявное преобразование из std::unique_ptr<Derived>
в std::unique_ptr<Base>
, поэтому эта перегрузка допустима, но для нее требуется преобразование.
Во втором случае F
просто выводится как std::unique_ptr<Derived>
. Он не требует преобразования и более близко соответствует предоставленному аргументу. Поэтому оно является предпочтительным.
Редактировать: Кажется, я пропустил часть об исправлении.
Вы можете сделать перегрузку, которая принимает вместо unique_ptr
шаблон функции. Таким образом, вы можете получить точное совпадение с первой перегрузкой, устраняя необходимость в преобразовании. Вы можете использовать std::enable_if
, чтобы отключить эту перегрузку для unique_ptr
s несовместимых типов:
#include <memory>
#include <type_traits>
class Base {};
class Derived : public Base {};
template<class T>
std::enable_if_t<std::is_base_of<Base, T>::value>>
call(std::unique_ptr<T>);
template<class T>
void call(T);