Проблемы с реализацией конструктора перемещения unique_resource из p0052r2 - PullRequest
0 голосов
/ 07 февраля 2019

Я пытаюсь реализовать уникальный_ресурс из предложения p0052r2.

http://www.open -std.org / jtc1 / sc22 / wg21 / docs /apers / 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. [Примечание.time.— end note] Затем, если is_nothrow_move_constructible_v имеет значение true, инициализировать удалитель вперед (rhs.deleter), в противном случае инициализировать удалитель из rhs.deleter.Если конструкция удалителя создает исключение: если! Is_nothrow_move_constructible_v, то rhs.deleter (resource).

У меня есть два вопроса по этому поводу.

  1. Почему следуетЯ инициализирую, используя forward (rhs.resource) или rhs.resource вместо std :: move (rhs.resource).То же самое для D.

  2. Как правильно реализовать обработку исключений?

Только если выдает конструктор удалителя, я должен освободитьresource.

В настоящее время у меня есть:

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 функции также включает конструирование ресурса.Что я могу сделать, чтобы перехватывать только исключения для средства удаления, не вводя вызов конструктору по умолчанию средства удаления.

Редактировать:

Мне кажется, я нашел ответ на второйвопрос основан на комментариях 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 ++ гарантирует отмену копирования для возвращаемого значения.

...