从p0052r2

时间:2019-02-07 13:40:42

标签: c++ exception-handling move-semantics move-constructor

我尝试从p0052r2提案中实施unique_resource。

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0052r2.pdf

提案中的构造函数声明为:

unique_resource(unique_resource&& rhs) 
    noexcept(is_nothrow_move_constructible_v<R> && 
             is_nothrow_move_constructible_v<D>);

其中R是资源,D是删除器。

行为描述如下:

  

如果is_nothrow_move_constructible_v为true,则初始化资源   从forward(rhs.resource),否则从初始化资源   rhs.resource。[注意:如果资源构造抛出   exceptionrhs保留了资源的所有权,并将在适当时释放资源   时间。—尾注]如果is_nothrow_move_constructible_v为true   从forward(rhs.deleter)初始化Deleter,否则初始化   rhs.deleter的删除器。如果删除器的构造抛出   例外:如果!is_nothrow_move_constructible_v,则   rhs.deleter(资源)。

对此我有两个问题。

  1. 为什么我应该使用forward(rhs.resource)或rhs.resource而不是std :: move(rhs.resource)进行初始化。对于D也是一样。

  2. 如何正确实施异常处理?

仅当删除程序的构造函数抛出异常时,才应释放资源。

我目前有:

CUniqueResource(CUniqueResource&& rhs) try
    : executeOnDestruction(rhs.executeOnDestruction)
    , resource(std::move(rhs.resource))
    , deleter(std::move(rhs.deleter))
{
    rhs.release();
}
catch (...)
{
    if constexpr(!std::is_nothrow_move_constructible_v<R>)
    {
        rhs.deleter(resource);
    }

    throw;
}

问题在于函数try块也包含了资源的构造。我该怎么做才能仅捕获deleter的异常,而无需引入对deleter的默认构造函数的调用。

编辑:

我想我根据eerorika的评论找到了第二个问题的答案。使用成员函数代替子对象。

代码如下:

CUniqueResource(CUniqueResource&& rhs)
    : executeOnDestruction(rhs.executeOnDestruction)
    , resource(std::move(rhs.resource))
    , deleter(acquireDeleter(rhs))
{
    rhs.release();
}

D acquireDeleter(CUniqueResource&& rhs)
{
    try
    {
        return D(std::move(rhs.deleter));
    }
    catch(...)
    {
        if constexpr(!std::is_nothrow_move_constructible_v<R>)
        {
            rhs.deleter(this->resource);
        }

        throw;
    }
}

我认为这应该可行,因为C ++保证返回值使用复制省略号。

0 个答案:

没有答案
相关问题