Browse Source

add NiklasRosenstein/context.hpp

master
Niklas Rosenstein 3 years ago
parent
commit
87035234f1
Signed by: NiklasRosenstein GPG Key ID: 06D269B33D25F6C6
1 changed files with 72 additions and 0 deletions
  1. + 72
    - 0
      include/NiklasRosenstein/context.hpp

+ 72
- 0
include/NiklasRosenstein/context.hpp

@ -0,0 +1,72 @@
/**
* Copyright (c) 2018 Niklas Rosenstein
* MIT licensed.
*
* @description This header provides an interface for creating context
* managers in C++ similar to what you have in Python.
*/
#pragma once
#include <functional>
namespace niklasrosenstein {
/* Base class for context managers. A context manager can only be moved and
* not copied. It will call a function when it is destroyed (be careful
* about closure scope being destroyed when returned from a function). */
class ctx_manager {
friend class exit_stack;
std::function<void()> _func;
public:
ctx_manager() : _func() {}
ctx_manager(ctx_manager const& other) = delete;
ctx_manager(ctx_manager&& other) : _func(std::move(other._func)) { other._func = {}; }
ctx_manager(std::function<void()>&& f) : _func(std::move(f)) {}
ctx_manager(std::function<void()> const& f) : _func(f) {}
~ctx_manager() { if (_func) _func(); }
ctx_manager& operator = (ctx_manager const& other) = delete;
ctx_manager& operator = (ctx_manager&& other) {
_func = std::move(other._func);
other._func = {};
return *this;
}
operator bool () const { return (bool) _func; }
};
/* Represents a stack of functions that will be called when the
* exit_stack is destroyed. */
struct exit_stack {
std::vector<std::function<void()>> callbacks;
inline exit_stack() {}
inline exit_stack(std::function<void()>&& func) { callbacks.push_back(std::forward<std::function<void()>>(func)); }
inline exit_stack(ctx_manager&& func) { this->operator << (std::forward<ctx_manager>(func)); }
inline ~exit_stack() {
for (auto it = callbacks.rbegin(); it != callbacks.rend(); ++it) {
(*it)();
}
}
inline exit_stack& operator << (std::function<void()>&& func) {
callbacks.push_back(std::forward<std::function<void()>>(func));
return *this;
}
inline exit_stack& operator << (ctx_manager&& ctx) {
if (ctx._func) {
callbacks.push_back(std::move(ctx._func));
ctx._func = {};
}
return *this;
}
inline void clear() {
callbacks.clear();
}
};
} // namespace niklasrosenstein

Loading…
Cancel
Save