在unique_ptr中使用模板和继承时的重载解析

Nik*_*ond 5 c++ overload-resolution

我有两节课:

class Base {};
class Derived : public Base {};
Run Code Online (Sandbox Code Playgroud)

还有两个重载函数:

void call(std::unique_ptr<Base> op)
{
    std::cout << "First overloading" << std::endl;
}

template<class F>
void call(F f) 
{
    std::cout << "Second overloading" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

用Derived的unique_ptr来称呼它

call(std::make_unique<Derived>());
Run Code Online (Sandbox Code Playgroud)

我希望调用第一个函数,但是调用第二个函数。为什么编译器选择通用函数而不是特定函数?重载解析不支持继承和多态吗?如果是这样,我该如何修复它并调用第一个函数?

Fra*_*eux 6

您的两个重载都是有效的候选者。如果删除其中任何一个,则其余的仍然是有效的重载。从广义上讲,在这种情况下,将选择的重载将与提供的参数最接近。

您提供了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);
Run Code Online (Sandbox Code Playgroud)