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.
}
Ответы
Ответ 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));
}
Ответ 4
Как насчет unique_ptr
из interprocess библиотека?
Ответ 5
Я использовал Howard Hinnant unique_ptr. Если вы не очень хорошо читаете сумасшедшие ошибки метапрограммирования из своего компилятора, вы можете захотеть четко понять. Однако он действует как уникальный_ptr в 90% случаев.
В противном случае я бы предложил передать параметры как boost::scoped_ptr&
и обмениваться внутри, чтобы украсть собственность. Чтобы получить возвращаемые значения стиля unique_ptr, используйте auto_ptr
. Захватите возвращаемое значение auto_ptr
в shared_ptr
или scoped_ptr
, чтобы избежать прямого использования auto_ptr
.