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

时间:2015-01-17 14:39:57

标签: c++ unique-ptr raii

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

为了将其分解,我有一个类具有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_;
};

我想包装Resource返回的Helper::get_resource(),但无法解决如何使用std::unique_ptr提供对Helper实例的访问权限仿函数中的类:

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
}

1 个答案:

答案 0 :(得分:0)

根据JoachimCasey的建议,我可以通过在函数中存储指向Helper类实例的指针来实现它:

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
}

它似乎有点脆弱(记得每次都分配帮助器实例),但它确实按预期工作。