Last active
August 6, 2022 17:53
-
-
Save david-bakin/f9e0ee2b8bba3db390ab6e53dc0ef6a0 to your computer and use it in GitHub Desktop.
O'Dwyer's Auto macro - hygenic scope guard w/ zero overhead
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
# O'Dwyer's Auto macro - hygenic scope guard w/ zero overhead | |
# https://quuxplusone.github.io/blog/2018/08/11/the-auto-macro/ | |
# | |
# "This scope guard has perfect codegen with zero overhead (at `-O2`) on all major compilers." | |
# "Because it requires no explicit captures, no novel variable name, no special treatment for `this`, | |
# it is highly suited for mechanically generated code." | |
# "It is portable all the way back to C++11." | |
template<class L> | |
class AtScopeExit { | |
L& m_lambda; | |
public: | |
AtScopeExit(L& action) : m_lambda(action) {} | |
~AtScopeExit() { m_lambda(); } | |
}; | |
#define TOKEN_PASTEx(x, y) x ## y | |
#define TOKEN_PASTE(x, y) TOKEN_PASTEx(x, y) | |
#define Auto_INTERNAL1(lname, aname, ...) \ | |
auto lname = [&]() { __VA_ARGS__; }; \ | |
AtScopeExit<decltype(lname)> aname(lname); | |
#define AUTO_INTERNAL2(ctr,..) \ | |
Auto_INTERNAL1(TOKEN_PASTE(Auto_func, ctr), \ | |
TOKEN_PASTE(Auto_instance_, ctr), __VA_ARGS__) | |
#define Auto(...) \ | |
Auto_INTERNAL2(__COUNTER__, __VA_ARGS__) | |
# Example: | |
# Auto(foo->cleanup()); | |
# Nesting example: | |
# Auto( | |
# puts("start 1"); | |
# Auto(puts("cleanup 2")); | |
# puts("getting ready to clean up after 1"); | |
# ); | |
# "I don't always use ad-hoc scope guards, but when I do, I prefer 'auto.h'." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment