【问题标题】:One struct with unique_ptr fields but with different deleters一个具有 unique_ptr 字段但具有不同删除器的结构
【发布时间】:2013-04-22 10:32:56
【问题描述】:

使用 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;
}

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

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

您是否有改进或干净的解决方案来允许结构为其成员拥有自定义的 unique_ptr 删除器?

注意我知道我可以进行模板专业化,但这实际上是在复制结构。

【问题讨论】:

  • 为什么会有递归声明?这种方法在原则上看起来很合理。
  • 因为default_delete需要一个模板,这个模板是类名,但是类名有一个模板,而这个模板有default_delete等等...
  • 我不明白。你可以说C&lt;std::default_deleter&lt;F&gt;&gt;,也可以说C&lt;DevDeleter&gt;。没有什么递归的吗?!
  • 在我的客户端代码中,我需要提供 T 和 T 在我的情况下将是 default_delete (再次)等等 :):):)。
  • 你能举一个最小的完整例子吗?

标签: c++ visual-studio-2010 templates cuda unique-ptr


【解决方案1】:

我想这就是你想要的:

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>;

【讨论】:

  • 感谢您的聊天,感谢您给我准确的答案!诀窍在于您提供的模板声明。
【解决方案2】:

这样做:

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));

【讨论】:

  • 不能使用构造函数。并且可能 struct 包含许多字段,而不仅仅是一个,而您的解决方案使 T 成为一个字段。我希望整个结构(未知数量的字段)能够在不同的上下文中运行。
【解决方案3】:

作为@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 似乎有点可疑,您通过 struct C “附加”了删除逻辑,而不是在创建这些唯一指针的位置。这可能是合法的,但我会调查一下。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-25
    • 1970-01-01
    • 2016-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-26
    • 1970-01-01
    相关资源
    最近更新 更多