将原始指针传递给接受unique_ptr作为参数的函数

Kam*_*nji 0 c++ templates smart-pointers

我正在尝试编写一个函数,接受unique_ptr到Base作为参数派生的类(表示所有权转移).我想出了以下代码:

#include <memory>
#include <type_traits>

class Base
{
  public:
    Base() {}
};

class Derived : public Base
{
  public:
    Derived() {}
};


void foo(std::unique_ptr<Derived> _data) {}

template <class T>
void boo(std::unique_ptr<T> _data) {
    static_assert(std::is_convertible<T*, Base*>::value,
                  "Only classes derived from Base can be used as "
                  "parameter for boo");
}


int main() { foo(new Derived); }
Run Code Online (Sandbox Code Playgroud)

但是当我尝试编译它时,我得到并且错误地告诉我,could not convert ‘(operator new(1ul), (<statement>, ((Derived*)<anonymous>)))’ from ‘Derived*’ to ‘std::unique_ptr<Derived>’如果我在使用时使用foo和相同(加上一些模板细节)boo.如果我正确地理解了一切,我被告知的是没有构造函数std::unique_ptr<Derived>可以接受指针Derived.但是当我在unppue_ptr构造函数的cppreference 页面上查看时,我看到有这样的构造函数(编号3-4).

问题是:我如何创建一个接受unique_ptr参数的函数并用原始指针调用它.

PS我正在尝试编写一个接受的函数,unique_ptr因为我想表明参数的所有权将被转移.如果您知道如何编写一个带有签名的函数,该签名可以清楚明确地表明所有权正在转移,我也会接受这个作为答案.此函数可以使用static_assert或使用Base指针作为参数进行模板.

PS主要问题是如何制作foo(new Derived).我知道我可以使用boo(std::make_unique<Derived>())(在这种情况下一切正常)但我也真的想知道为什么带有原始指针的例子不起作用,因为我不知道如何表明我正在"窃取"原始指针的所有权.

PS使用示例(带原始指针)(不工作)

Derived* derived_1 = new Derived;
// Do something with derived_1
boo(derived_1); // Pass to function and don't worry about `delete`
                // because you know that ownership has been
                // transferred and no longer is your concern
Run Code Online (Sandbox Code Playgroud)

并有智能指针

void foo_2(std::unique_ptr<Derived>& _data) {
     boo(std::move(_data)); 
}

std::unique_ptr<Derived> derived_2 = std::make_unique<Derived>();
// Do something with derived_2
foo(std::move(derived_2)); // Have to use `std::move`
                           // or
foo_2(derived_2);
Run Code Online (Sandbox Code Playgroud)

第二个(省略对新功能的需求)并不像第一个那么简单(尽管我应该承认差异不是那么大(可能是2x打字))

Nat*_*ica 8

过载3和4不适用于此处.他们的签名是

unique_ptr( pointer p, /* see below */ d1 ) noexcept;

unique_ptr( pointer p, /* see below */ d2 ) noexcept;
Run Code Online (Sandbox Code Playgroud)

它们采用第二个参数,即自定义删除器.唯一适用的重载是2

explicit unique_ptr( pointer p ) noexcept;
Run Code Online (Sandbox Code Playgroud)

由于它被标记为显式,因此不会将指针隐式转换为a unique_ptr.这是一个安全问题,明确说明是正确的.如果不是explicit那么的话

void foo(std::unique_ptr<int> _data) {}

int main()
{
    int bar;
    foo(&bar);
}
Run Code Online (Sandbox Code Playgroud)

会编译,但它将是未定义的行为,因为_data尝试删除指针在它结束时被销毁foo.