简体   繁体   中英

Where can I find a good Scope Guard implementation for my C++ projects?

I just recently learned about Scope Guard C++ idiom. Unfortunately I can't find any good implementation of it.

Can anyone point me to some good and usable Scope Guard implementation in C++?

Thanks, Boda Cydo.

The original ScopeGuard class is included in this Dr. Dobb's article by Andrei Alexandrescu and Petru Marginean. A slightly improved version, with some changes from Joshua Lehrer is available here . (Lehrer's version is the one that I'm using in my projects.) It's also included in the Loki library.

Boost now has a ScopeExit library that's more powerful than ScopeGuard (since it can execute arbitrary code, whereas ScopeGuard can only call a single preexisting function).

Edit: With all of that said, a Scope Guard is really just a specific application of RAII, so you really ought to at least understand the concept of how to implement one.

ScopeGuard has been included in the Loki library (advertised in Modern C++ Design by Andrei Alexandrescu, I'm sure you've heard of this great book), and is mature enough to be used in production code, imo.

Just to be clear: We're talking about writing exception safe code using RAII.

Additional reading (on StackOverflow): Does ScopeGuard use really lead to better code?

The Folly library (open-source from facebook) also provides an implementation (not surprising since AA is employed by them):

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

I think this and the MNMLSTC implementation mentioned here are both worth consideration.

There's a proposal to add scope_guard to the standard library. You can read the paper, which includes a sample implementation you can copy/paste, here . See section 9.1 for the implementation.

MNMLSTC 核心具有范围保护习语的现代 C++11 实现

A "Scope Guard" object is just one instance of the much broader RAII idiom.

And there is no single implementation of that. It is something a C++ programmer has to understand , not just copy/paste. Luckily, it is also pretty trivial to implement.

You create a class which represents some kind of resource. When the class is instantiated (by one of its constructors), it should acquire the resource, and throw an exception if that fails. When the class is destroyed, it should dispose of the resource, performing all the necessary cleanup.

And... that's it. You also have to handle copy constructor and assignment operator (either by cloning the resource or by making these two functions private so they're never called).

You don't need to find "a good implementation", because you're going to write dozens and dozens of different implementations yourself. They're trivial to write, and they can't easily be reused because each one wraps a different type of resource.

Let me offer a basic C++20 version.

#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>>;

Please note that unless we need to move the scope_guard around, it adds zero memory overhead over Cleanup callable, because we don't need to hold it in a resettable manner, because we don't need move constructor, because we got class template argument deduction.

A fine example of how expressive the language became. Thank you commitee!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM