一个具有unique_ptr字段的结构体,但具有不同的删除器

One struct with unique_ptr fields but with different deleters

本文关键字:结构体 删除 ptr 一个 unique 字段      更新时间:2023-10-16

使用Visual Studio 2010,我有:

using namespace std;
struct C 
{
    unique_ptr<F1, default_delete<F1>> Field1;
    unique_ptr<F2, default_delete<F1>> Field2;
    unique_ptr<FN, default_delete<F1>> FieldN;
}

它将在两个上下文中使用,CPU和GPU,在CPU上下文中,结构体和字段将具有default_delete,在GPU上下文中,使用CUDA,他们将有一个自定义删除器,使用cudaFree函数来删除。

可能使用的自定义删除器看起来像这样

struct DevDeleter
{
    void operator()(void* d_ptr)
    {
        cudaError_t error = cudaFree(d_ptr);
        if (error != cudaSuccess)
        {
            throw;
        }
    }
}

所以,我的第一个预感是看一下模板,我的结构变成了:

template<typename Deleter> 
struct C 
{
    unique_ptr<F1, Deleter> Field1;
    unique_ptr<F2, Deleter> Field2;
    unique_ptr<FN, Deleter> FieldN;
}

我有一个结构体框架(超过30)需要在2个删除上下文中工作。如果我想在某个函数中声明struct C,这将有一个递归声明,不能这样写:

unique_ptr<C<default_delete<C<default_delete<C<(recursive)>>>>, default_delete<C(recursive)>> c(new C<...>());

你有一个改进或干净的解决方案,允许一个结构有自定义的unique_ptr delete为其成员?

注意:我知道我可以做模板专门化,但这实际上是在复制结构体。

我想这就是你想要的:

template <typename T>
struct DevDeleter
{
    void operator()(T* d_ptr)
    {
        cudaError_t error = cudaFree(d_ptr);
        if (error != cudaSuccess)
        {
            throw;
        }
    }
}

那么你可以有一个这样的模板:

template<template <typename> class Deleter>
struct C 
{
    unique_ptr<F1, Deleter<F1>> Field1;
    unique_ptr<F2, Deleter<F2>> Field2;
    unique_ptr<FN, Deleter<FN>> FieldN;
}

,并像这样命名:

C c_default<default_delete>;

C c_dev<DevDeleter>;

这样做:

template <typename T, typename D = std::default_deleter<T>> struct Foo
{
    std::unique_ptr<T, D> up;
    Foo(D const & d = D()) : up(nullptr, d) { }
};

的例子:

// contains std::unique_ptr<int, std::default_deleter<int>>
Foo<int> x;
// contains std::unique_ptr<Bar, BarDeleter>
Foo<Bar, BarDeleter> y(BarDeleter(1, true, Blue));

作为@VaughCato回答的延伸,可以考虑这样写:

template<template <typename> class Deleter = std::default_delete>
struct C 
{
    template <typename T> using unique_ptr = unique_ptr<T, Deleter<T>>;
    unique_ptr<F1> Field1;
    unique_ptr<F2> Field2;
    unique_ptr<FN> FieldN;
}

调用将是这样的:

C<> c1;               // defaults to default_delete ...
C<default_delete> c2; // same thing but explicit
C<DevDeleter> c3;     // on device

H-o-w-e-v-e-r似乎有点可疑,你有删除逻辑"追加"通过结构体C,而不是在你创建那些唯一的指针。这可能是合法的,但我会调查一下。