初始化传递给 unique_ptr 自定义删除器的仿函数

Initialise a functor passed into a unique_ptr custom deleter

我正在使用 RAII 通过使用 std::unique_ptr 和自定义删除器来管理我的代码中的资源。到目前为止,这是相对微不足道的,但我现在想为需要访问现有托管资源作为其清理仿函数的一部分的资源添加 RAII 包装器。

为了分解它,我有一个 class,它有一个 RAII 管理的资源,可以获取依赖于它的额外资源:

struct CloseHandleFunctor
{
    typedef HANDLE pointer;
    void operator()(const HANDLE h)
    {
        ::CloseHandle(h);
    }
};

using AutoHandle = std::unique_ptr<HANDLE, CloseHandleFunctor>;

class Helper
{
public:
    // acquires a resource associated with h_
    Resource get_resource();
    // releases the resource acquired by get_resource()
    void release_resource(const Resource res);
    // ...
private:
    AutoHandle h_;
};

我想包装 Helper::get_resource() 返回的 Resource,但不知道如何使用 std::unique_ptr 来提供对 Helper 实例的访问class 在函子中:

struct ReleaseResourceFunctor
{
    typedef Resource pointer;
    void operator()(Helper h, const Resource r)
    {
        h.release_resource(r);
    }
};

using AutoResource = std::unique_ptr<Resource, ReleaseResourceFunctor>;
   // no way to pass the instance of Helper ~~~^

我想这样使用它:

int main()
{
    Helper h;

    {
        AutoResource res(h.get_resource());
    }
    // h.release_resource() gets called
}

正如 and 所建议的,我可以通过在仿函数中存储指向 Helper class 实例的指针来使其工作:

struct ReleaseResourceFunctor
{
    typedef Resource pointer;

    Helper *helper_;

    ReleaseResourceFunctor()
        : helper_(nullptr)
    {
    }

    void setHelper(Helper * const h)
    {
        helper_ = h;
    }

    void operator()(const Resource r)
    {
        if (helper_ != nullptr)
        {
            helper_->release_resource(r);
        }
    }
};

...然后在构建 std::unique_ptr:

之后分配助手实例
int main()
{
    Helper h;

    {
        AutoResource res(h.get_resource());
        res.get_deleter().setHelper(&h);
    }
    // h.release_resource() gets called as expected
}

看起来有点脆弱(记得每次都分配 helper 实例),但它确实按预期工作。