C ++通过值传递模板化的unique_ptr

tur*_*oni 1 c++ c++14

我有一个派生类,我想创建一个unique_ptr并将其传递给函数。我可以这样做,如下所示:

#include <memory>

struct Base{};

struct Derived : public Base
{};

void foo(std::unique_ptr<Base> sink)
{    
}

int main(){
    foo(std::make_unique<Derived>());    

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是当我想使用Derived作为模板来执行此操作时,它将不再编译:

#include <memory>

struct Dummy
{};

template<class D>
struct Base{};

template<class D>
struct Derived : public Base<D>
{};

template<class D>
void foo(std::unique_ptr<Base<D>> sink)
{    
}

int main(){
    foo(std::make_unique<Derived<Dummy>>()); //does not compile    
    //foo(std::unique_ptr<Base<Dummy>>(new Derived<Dummy>())); // compiles

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我可以通过定义基本唯一ptr并使用派生的裸指针对其进行初始化来解决此问题。

foo(std::unique_ptr<Base<Dummy>>(new Derived<Dummy>()));
Run Code Online (Sandbox Code Playgroud)

但是,这似乎有些错误。

是否有我为什么无法编译的原因?
另外还有其他方法让我错过如何使用模板化类并且不需要使用裸指针的方法吗?

编译mcve1
编译mcve2

Joã*_*ulo 5

在这种情况下,编译器只是无法推断出类型。您可以通过传递类型来帮助它:

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

但是,如果您这样声明foo

template <template<class, class> class X, class Y, class Z>
void foo(X<Y,Z> sink) {}
Run Code Online (Sandbox Code Playgroud)

或像这样:

template<class D, class S>
void foo(std::unique_ptr<D, S> sink){}
Run Code Online (Sandbox Code Playgroud)

它将同时适用于:

foo(std::make_unique<Derived<Dummy>>());
foo(std::unique_ptr<Base<Dummy>>(new Derived<Dummy>()));
Run Code Online (Sandbox Code Playgroud)