буст-эквивалент unique_ptr? - PullRequest
54 голосов
/ 02 июня 2010

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

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.
}

РЕДАКТИРОВАТЬ: Прямо сейчас я использую этот хак, который кажется лучшим, что я могу получить на данный момент ...

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.
}

Ответы [ 5 ]

68 голосов
/ 02 июня 2010

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

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

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

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

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

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

(...) замена вставки для std :: unique_ptr, также используемая в C ++ 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 в режиме C ++ 98 (!).

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

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

Подробнее см. в списке рассылки Boost .

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

10 голосов
/ 02 июня 2010

Возможно, вы захотите попробовать «доказательство концепции» Говарда Хиннанта. unique_ptr<> Реализация для C ++ 03 (отказ от ответственности - не знаю):

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

unique_ptr<int> factory(int i)
{
    return unique_ptr<int>(new int(i));
}
5 голосов
/ 02 июня 2010

Как насчет unique_ptr из библиотеки interprocess ?

4 голосов
/ 02 июня 2010

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

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

...