Где я могу найти хорошую реализацию Scope Guard для моих проектов C++?

Я только недавно узнал об идиоме Scope Guard C++. К сожалению, я не могу найти хорошую реализацию этого.

Может кто-нибудь указать мне на хорошую и полезную реализацию Scope Guard в C++?

Спасибо, Бода Кидо.

7 ответов

Решение

ScopeGuard был включен в библиотеку Loki (анонсирован Андреем Александреску в Modern C++ Design, я уверен, что вы слышали об этой замечательной книге) и достаточно зрел, чтобы его можно было использовать в рабочем коде, imo.

Просто чтобы прояснить: мы говорим о написании безопасного кода с использованием RAII.

Дополнительное чтение (в Stackru): действительно ли использование ScopeGuard приводит к улучшению кода?

Оригинальный класс ScopeGuard включен в статью доктора Добба, написанную Андреем Александреску и Петру Марджиняном. Слегка улучшенная версия с некоторыми изменениями от Джошуа Лерера доступна здесь. (Версию Лерера я использую в своих проектах.) Она также включена в библиотеку Loki.

Boost теперь имеет библиотеку ScopeExit, которая является более мощной, чем ScopeGuard (поскольку она может выполнять произвольный код, тогда как ScopeGuard может вызывать только одну существующую ранее функцию).

Редактировать: С учетом всего вышесказанного Scope Guard - это на самом деле просто конкретное приложение RAII, так что вы действительно должны хотя бы понять концепцию его реализации.

Библиотека Folly (с открытым исходным кодом из Facebook) также предоставляет реализацию (что неудивительно, поскольку они используют AA):

https://github.com/facebook/folly/blob/master/folly/ScopeGuard.h

Я думаю, что это и реализация MNMLSTC, упомянутые здесь, заслуживают рассмотрения.

Позвольте мне предложить базовую версию C++20.

      #include <concepts>
#include <type_traits>

template <std::invocable Cleanup>
class [[nodiscard]] scope_guard
{
    Cleanup d;
public:
    scope_guard(Cleanup&& d) : d{std::forward<Cleanup>(d)} {}
    scope_guard(const scope_guard&) = delete;

    ~scope_guard(){d();}
};

// allow construction from plain function
template <typename F>
scope_guard(F&&) -> scope_guard<std::decay_t<F>>;

Обратите внимание, что если нам не нужно переместить вокруг, это добавляет нулевые накладные расходы памяти по сравнению с callable, потому что нам не нужно хранить его с возможностью сброса, потому что нам не нужен конструктор перемещения, потому что мы получили вывод аргумента шаблона класса.

Прекрасный пример того, насколько выразительным стал язык. Спасибо комитету!

Объект "Scope Guard" является лишь одним из примеров гораздо более широкой идиомы RAII.

И нет единой реализации этого. Это то, что программист на С ++ должен понимать, а не просто копировать / вставлять. К счастью, это также довольно тривиально реализовать.

Вы создаете класс, который представляет какой-то ресурс. Когда создается экземпляр класса (одним из его конструкторов), он должен получить ресурс и выдать исключение в случае сбоя. Когда класс уничтожен, он должен избавиться от ресурса, выполнив всю необходимую очистку.

И это все. Вы также должны обработать конструктор копирования и оператор присваивания (либо путем клонирования ресурса, либо сделав эти две функции частными, чтобы они никогда не вызывались).

Вам не нужно находить "хорошую реализацию", потому что вы собираетесь написать десятки и десятки различных реализаций самостоятельно. Их написать несложно, и их нелегко использовать повторно, поскольку каждый из них оборачивает свой тип ресурса.

Есть предложение добавить scope_guard в стандартную библиотеку. Вы можете прочитать статью, которая включает пример реализации, которую вы можете скопировать / вставить, здесь. См. Раздел 9.1 для реализации.

Ядро MNMLSTC имеет современную C++11 реализацию языка видимости.

Другие вопросы по тегам