Подтвердить что ты не робот

Unique_ptr boost эквивалент?

Есть ли эквивалентный класс для С++ 1x std:: unique_ptr в библиотеках boost? Поведение, которое я ищу, может иметь безопасную для исключения функцию factory, например...

std::unique_ptr<Base> create_base()
{
    return std::unique_ptr<Base>(new Derived);
}

void some_other_function()
{
    std::unique_ptr<Base> b = create_base();

    // Do some stuff with b that may or may not throw an exception...

    // Now b is destructed automagically.
}

EDIT: Прямо сейчас, я использую этот хак, который кажется лучшим, что я могу получить в этот момент...

Base* create_base()
{
    return new Derived;
}

void some_other_function()
{
    boost::scoped_ptr<Base> b = create_base();

    // Do some stuff with b that may or may not throw an exception...

    // Now b is deleted automagically.
}
4b9b3361

Ответ 1

Невозможно создать нечто вроде unique_ptr без С++ 0x (где он является частью стандартной библиотеки, и поэтому Boost не нужно его предоставлять).

В частности, без ссылок на rvalue, которые являются признаком в С++ 0x, надежная реализация unique_ptr невозможна с Boost или без нее.

В С++ 03 есть несколько возможных альтернатив, хотя у каждого есть свои недостатки.

  • boost::shared_ptr - вероятно, самая простая замена с точки зрения возможностей. Вы можете безопасно использовать его везде, где вы в противном случае использовали бы unique_ptr, и он сработает. Это было бы не так эффективно, потому что добавленный подсчет ссылок. Но если вы ищете простую замену, которая сможет обрабатывать все, что может сделать unique_ptr, это, вероятно, лучший выбор. (Конечно, shared_ptr может делать намного больше, но его также можно просто использовать в качестве замены для unique_ptr.)
  • boost::scoped_ptr похож на unique_ptr, но не позволяет передавать права собственности. Он отлично работает, пока умный указатель предназначен для сохранения исключительной собственности на протяжении всей своей жизни.
  • std::auto_ptr работает очень похоже на unique_ptr, но имеет несколько ограничений, в основном, что он не может быть сохранен в стандартных библиотечных контейнерах. Если вы просто ищете указатель, который позволяет передавать права собственности, но который не предназначен для хранения в контейнерах или скопирован, это, вероятно, хорошая ставка.

Ответ 2

Начиная с Boost 1.57 существует официальная реализация unique_ptr в библиотеке Boost.Move.

Из документации:

(...) вставная замена для std::unique_ptr, используемая также из С++ 03 Составители.

Код доступен в заголовочном файле <boost/move/unique_ptr.hpp> и находится в пространстве имен boost::movelib. Кроме того, библиотека Boost.Move обеспечивает фабричную функцию make_unique() в <boost/move/make_unique.hpp>, также в пространстве имен boost::movelib.

Следовательно, пример из вопроса может быть реализован следующим образом:

#include <boost/move/unique_ptr.hpp>

using boost::movelib::unique_ptr;

unique_ptr<Base> create_base()
{
    return unique_ptr<Base>(new Derived);
}

Смотрите живой пример на Wandbox. Обратите внимание, что код прекрасно компилируется с помощью gcc 4.6.4 в режиме С++ 98 (!).

Что интересно в boost::movelib::unique_ptr применительно к вашему случаю с базовыми/производными классами, реализация обеспечивает проверку во время компиляции для объявления виртуального деструктора в базовом классе. Если вы пропустите его , код не скомпилируется (нажмите кнопку "Выполнить (...)", чтобы увидеть сообщение об ошибке компилятора).

Одна небольшая проблема заключается в том, что сюда входят файлы из каталога boost/move, но код находится в пространстве имен boost::movelib (небольшая разница, но она может раздражать).

См. также тему в расширенной рассылке для получения дополнительной информации.

Спасибо Иону Газтаньяге за этот абсолютно уникальный и полезный фрагмент кода.

Ответ 3

Возможно, вы захотите попробовать версию доказательств концепции unique_ptr<> для Howard Hinnant для С++ 03 (отказ от ответственности - я не знаю):

Один из его примеров возвращает unique_ptr<int>:

unique_ptr<int> factory(int i)
{
    return unique_ptr<int>(new int(i));
}

Ответ 5

Я использовал Howard Hinnant unique_ptr. Если вы не очень хорошо читаете сумасшедшие ошибки метапрограммирования из своего компилятора, вы можете захотеть четко понять. Однако он действует как уникальный_ptr в 90% случаев.

В противном случае я бы предложил передать параметры как boost::scoped_ptr& и обмениваться внутри, чтобы украсть собственность. Чтобы получить возвращаемые значения стиля unique_ptr, используйте auto_ptr. Захватите возвращаемое значение auto_ptr в shared_ptr или scoped_ptr, чтобы избежать прямого использования auto_ptr.