Last active
July 14, 2019 12:37
-
-
Save jstine35/21d1dc543a5f71ed65f03499918f06c3 to your computer and use it in GitHub Desktop.
Defer-style functionality for C++ (Defer concept borrowed from GoLang)
This file contains 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 | |
#include <functional> | |
// ----------------------------------------------------------------------------------------------- | |
// Defer (macro) / Defer_t (struct) | |
// | |
// Inspired by Golang's 'defer' keyword. Allows binding a lambda to be executed when the current | |
// scope of the deferral's creation is left. This still differs from Golang `defer`: | |
// | |
// - Golang defer executes at the end of function scope. | |
// - Our C++ Defer executes at the end of current lexical scope. | |
// | |
// Advantages: | |
// and also allows defining a custom deletion/destruction action without having to create | |
// custom wrapper class. If you want a long-winded version, then use Defer_t directly. | |
struct Defer_t { | |
std::function<void()> m_func; | |
private: | |
Defer_t(const Defer_t& rvalue) = delete; | |
void operator=(const Defer_t& rvalue) = delete; | |
public: | |
Defer_t(Defer_t&& rvalue) { | |
m_func = std::move(rvalue.m_func); | |
rvalue.m_func = nullptr; | |
} | |
Defer_t() throw() { } | |
Defer_t(const std::function<void()>& func) throw() { | |
m_func = func; | |
} | |
~Defer_t() { | |
m_func(); | |
} | |
void Bind(const std::function<void()>& func) { | |
m_func = func; | |
} | |
}; | |
// ----------------------------------------------------------------------------------------------- | |
// Defer Macros | |
// | |
// Defer - Accepts a lambda or a function pointer as the parameter. | |
// | |
// DeferF - This has the lambda syntax and semi-colon baked-in on purpose. The point of this macro is maximum | |
// brevity for the most common case usage, which is to free a pointer or release a handle. | |
#define _defer_expand_counter_2(func,count) Defer_t defer_anon_ ## count( func ) | |
#define _defer_expand_counter_1(func,count) _defer_expand_counter_2(func, count) | |
#define Defer(func) _defer_expand_counter_1(func, __COUNTER__) | |
#define DeferF(function_content) Defer( [&]() { function_content; } ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment