将unique_ptrs深度复制到pmr资源(使用pmr分配器)



我基于多态内存资源重写了我的库。我认为它们很神奇,但也有一些边缘案例没有真正纳入标准。

例如,刚才我遇到了以下问题:类类型将unique_ptr保存到pmr分配的资源。现在,如何在复制构造函数中处理这个问题?底层的pmr资源(pmr::vector(必须使用pmr资源来构建(我认为它是使用pmr分配器自动传递的(。因此,我使用分配器的new_object()delete_object()功能来馈送我唯一的ptr。但它失败了,因为1(分配器不是删除函数(不为删除提供operator()重载(和/或2(我不能直接使用函数,因为这些函数是非静态的。如何解决此问题?

演示

#include <memory_resource>
#include <memory>
struct profile
{
using allocator_type = std::pmr::polymorphic_allocator<std::byte>;
profile(allocator_type allocator = {})
:   allocator_{allocator}
{}
profile(const profile& other, allocator_type allocator = {})
:   allocator_{ allocator }
{
// Deep copy vector (how to do this?)
auto f = std::pmr::polymorphic_allocator<std::byte>::delete_object;
vals_ = std::unique_ptr<profile, decltype(&f)>{ allocator_.new_object<profile>(), f };
}
allocator_type get_allocator() {
return allocator_;
}
allocator_type allocator_;
std::unique_ptr<std::pmr::vector<double>> vals_;
};

int main()
{
profile p;
profile o{p};
}

错误:

<source>:15:62: error: call to non-static member function without an object argument
auto f = std::pmr::polymorphic_allocator<std::byte>::delete_object;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~
1 error generated.
#include <memory_resource>
#include <memory>
struct profile
{
using allocator_type = std::pmr::polymorphic_allocator<std::byte>;

// This is a method
// std::pmr::polymorphic_allocator<std::byte>::delete_object<std::pmr::vector<double>>
// so if you want the unique_ptr to have deleter use this method you must
// also provide it the polymorphic_allocator that it should call this method on
// BUT
// you don't actually even need a unique_ptr to solve the problem
public:    

profile(allocator_type allocator = {})
: allocator_{allocator}
{}
profile(const profile& other, allocator_type allocator = {})
: allocator_{ allocator }
, vals_(std::begin(other.vals_), std::end(other.vals_), allocator_)
{
}
allocator_type get_allocator() {
return allocator_;
}
allocator_type allocator_;
std::pmr::vector<double> vals_;
};

int main()
{
profile p;
profile o{p};
}

unique_ptr是多余的,因为它只是在做ptr->ptr->实际数据现在是ptr->数据关于移动/复制构造->使用相同分配器实例的复制构造将正确运行(std::vector是可感知分配器的容器(分配器的不同实例(第二个构造函数(也是如此->您正在委派实现Allocator Aware Container的繁琐工作(https://en.cppreference.com/w/cpp/named_req/AllocatorAwareContainer->https://www.youtube.com/watch?v=kSWfushlvB8)到类中的实际容器->std::矢量显然,配置文件实例(甚至内部向量实例(的std::move将得到正确处理。

如果您有一个用例需要unique_ptr,那么它将变得更加复杂。unique_ptr具有以下模板签名:

template<class T, class Deleter>
class unique_ptr{[...]};

它不做任何类型的擦除,所以每次传递这个类的实例时,都需要提供deleter作为模板参数

这与具有以下签名的shared_ptr的情况不同:

template<class T>
class shared_ptr{[...]};

即使没有对应于deleter的模板参数,它也允许使用它们(https://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr)

因此,假设这个用例,您需要创建一个已知类型的函数类对象,该对象将是Deleter类型的参数,但这有几个缺点:

  • 要求您实现AllocatorAwareContainer
  • 使课堂逻辑大为复杂
  • 这不是一个好的代码实践(因为您正在类中合并两个功能,而这两个功能可能并不是专门针对任意数据的容器(

最新更新