我发现只有一个与std::unique_ptr
关联的非成员实用工具助手,它会调用new
。如果用于包装现有原始指针而不必明确命名类型的实用程序呢?
特别是,假设遗留代码或外部库具有以下内容:
C* foo(); // caller is responsible for deleting
也就是说,某些函数应该被写为返回unique_ptr<C>
,但不是,并且调用者无法更改它。
我认为使用此功能的正确方法是:
unique_ptr<C> up (foo());
但这需要命名类型,而不是使用auto
。它引出了一个问题,为什么没有一个帮助函数可以使用模板参数推导并写出如下内容:
auto up= capture_unique(foo());
理想情况下,甚至在声明变量时提供=
语法,以及单独确定类型。
这是一种自然的写作方式,我无法想象我是第一个想到它的人。是否有一些隐藏的危险使得在一般情况下无法写出这个?或者,作为标准的一部分,与make_unique
和unique_ptr
模板一起提供的原因是什么?
答案 0 :(得分:1)
满足您描述的要求的最简单的代码将是;
template<typename T>
auto capture_unique(T* ptr)
{
return std::unique_ptr<T>{ptr};
}
这样可以很好地处理示例代码;
auto up = capture_unique(foo());
capture_unique
和直接使用unique_ptr
构造函数之间几乎没有什么区别,除了你说的,重新输入类型C
。
auto up = std::unique_ptr<C>{foo()};
对于通用代码,您可以使用decltype
和declval
等。可能不存在广义用例。
同样的问题存在于std::shared_ptr
,其中再次没有“捕获”类型的辅助方法,再次,创建一个很简单。 shared_ptr
案例与unique_ptr
之间的区别在于,删除者是unique_ptr
而不是shared_ptr
类型的一部分。
是否存在一些隐藏的危险,这使得在一般情况下无法写出这一点?
没有隐藏的危险,只是关于使用什么类型的一些未回答的一般问题。但很容易创建,如上所述。
或者,作为标准的一部分,与
make_unique
和unique_ptr
模板一起提供的原因是什么?
删除器可能是该类型的一部分是不创建实用程序捕获方法的一个很好的理由(因此它不会镜像shared_ptr
)。如果删除器是默认的capture_unique
,delete
将无法提供更好的语法 - 它可能会更麻烦。
注意:“工厂”方法,make_unique
和make_shared
都使用new
运算符,并将其与默认的delete
删除器结合使用。