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.
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.
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 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 A.A. 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.
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!
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.
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 core has a modern C++11 implementation of the scope guard idiom.
© 2022 - 2024 — McMap. All rights reserved.
delete
but with scope guards you can alsodelete []
orfree
orfclose()
orclose_my_object
, etc. So I think it's better. Please correct me if I am wrong. – Hypertensiondelete
. See boost.org/doc/libs/1_43_0/libs/smart_ptr/…. Although I personally think a Scope Guard is clearer for cases likeclose_my_object
. – Deficit