如何将unique_ptr与更通用的deleter一起使用
How can I use unique_ptr with a more generic deleter?
考虑一些函数:
template<typename F>
void foo(F f) {
std::unique_ptr<int> p = f();
// do some stuff with p
}
因为unique_ptr
为D
指定了默认模板参数default_delete
,所以传递给foo
的任何函数对象如果返回具有非默认deleter的unique_ptr
,都无法编译。例如,
int x = 3;
foo([&x](){
// use empty deleter
return std::unique_ptr<int>(&x, [](int*){});
});
然而,我认为这可能是有用的,我看不出它不可能实现的直接原因。有没有一种共同的方法来解决这个问题?
编辑
简单的解决方案是定义foo
,而不是使用以下内容:
std::unique_ptr<int, std::function<void(int*)>> p = f();
但我想知道为什么这不能被纳入unique_ptr
的接口中?类接口不能提供这个泛型属性是有原因的吗?有没有办法将这种东西"包装"成一个新的定义?
例如,
template<typename T>
using Generic_unique_ptr =
std::unique_ptr<
T,
std::function< void(typename std::unique_ptr<T>::element_type*) >
>;
但这似乎很危险,因为它暴露了做以下事情的可能性,
Generic_unique_ptr<int> p(new int());
这将使删除程序未初始化并且表现出未定义的行为。也许有什么方法可以为提供std::default_delete<T>
的实例作为默认删除程序?
如果你只想在函数中使用指针,你可以使用auto
关键字;编译器将推导出unique_ptr
的类型它已经被使用,因此自动做正确的事情:
template <typename F>
void foo(F f)
{
auto p = f();
p->bar();
}
现在,从你的评论中,我们知道这不是你想要的全部,但你希望能够将unique_ptr
存储在您的类中以便使用稍后。这就产生了一系列完全不同的问题:
- CCD_ 12和CCD_。因此,我们需要知道您的函子
F
将返回什么unique_ptr<T, D>
- 即使我们事先知道
F
的返回类型,我们的类仍然只能存储unique_ptr<T, D1>
而不能存储unique_ptr<T, D2>
我能想到的最简单的方法可能是ways)是类型的擦除。
我们为自己创建了一个基类,该基类公开由unique_ptr
:
template <typename T>
struct wrapper
{
virtual ~wrapper() {}
virtual T const * get() const = 0;
virtual T * get() = 0;
};
从该类继承我们实际的存储类,该存储类推导类型unique_ptr
:
template <typename T, typename F>
struct storage
: wrapper<T>
{
storage(F f) { p_ = f(); }
T const * get() const { return p_.get(); }
T * get() { return p_.get(); }
private:
typename std::result_of<F()>::type p_;
};
在您真正关心的类中,您现在可以存储指向基类,并使用多态性来访问底层对象将CCD_ 21。假设我们将上面的类移动到namespace detail
对用户隐藏它们:
template <typename T>
class some_class
{
public:
template <typename F>
void store(F f)
{
storage_.reset(new detail::storage<T, F>(f));
}
T const * get() const { return storage_->get(); }
T * get() { return storage_->get(); }
private:
std::unique_ptr<detail::wrapper<T>> storage_;
};
你可以在这里找到一个完全有效的例子。
但我想知道为什么这不能被纳入unique_ptr的接口中?
因为这样做会迫使std::function
的所有开销都转移到每个上。unique_ptr
旨在对指针的单一所有权的几乎任何情况都很有用。你为你使用的东西付费;并不是每个使用自定义deleter的人都需要该deleter是泛型。这样,他们就不必为此付费。
此外,当前的方法允许它处理非指针资源,因为deleter可以准确地指定unique_ptr
中存储的类型。
如果您想提供这种通用的deleter构造,您可以创建一个类,该类(私下)继承自unique_ptr
并复制其接口,减去不使用deleter实例的构造函数。这样,用户就被迫在.
- 如何将enable-if与模板参数和参数包一起使用
- 如何将PERF_AMPLE_READ与mmap一起使用
- 如何将两个不同矢量的同一位置的两个元素组合在一起
- 如何将C++中的库和头与MinGW一起使用
- 将--whole archive链接器选项与CMake和具有其他库依赖项的库一起使用
- 为什么我不能将 rand() 与数组的大小一起使用?
- 要与"if constexpr"一起使用的编译时消息(在预处理器之后)
- 不能将复制初始化与隐式转换的多个步骤一起使用
- 将fold表达式与std::一起用于两个元组
- spdlog标头仅与外部fmt一起使用.spdlog错误:'内部':不是'fmt'
- 将 std::allocate_shared 与多态资源分配器一起使用
- 为什么常量词在重载运算符中不与 ostream 对象一起使用<<?
- 将 OpenCV 与 CMAKE 中的项目一起构建为第三方库的正确方法
- 将 exprtk 与自定义类的对象一起使用
- 将 std::set 与基于键的比较器一起使用
- 将 C++ 类与 Rcpp 一起使用,从 C 或 R 修改它
- 如何将 Eigen::Ref 与 pybind11 一起使用?
- 如何将AERT_Allocate与 std:vector 一起使用
- 如何使我的 sizeof sum 结构与空参数包一起工作
- 如何将unique_ptr与更通用的deleter一起使用