Last active
June 10, 2016 12:36
-
-
Save SeanCline/de2669b320743f42bed192b16ee14ba9 to your computer and use it in GitHub Desktop.
transacted<T> - Stores a copy of a type and writes the result back to the original unless an exception is thrown.
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
#include "transacted.h" | |
#include <iostream> | |
#include <stdexcept> | |
using namespace std; | |
int x = 1; | |
long y = 2; | |
float z = 3; | |
void doSomething() | |
{ | |
TRANSACTED(x, y, z); | |
++x; ++y; ++z; | |
} | |
void doSomethingButThrow() | |
{ | |
TRANSACTED(x, y, z); | |
++x; ++y; ++z; | |
throw runtime_error("Transaction not applied!"); | |
} | |
int main() | |
{ | |
cout << x << y << z << "\n"; | |
doSomething(); | |
cout << x << y << z << "\n"; | |
try { | |
doSomethingButThrow(); | |
} catch (const exception& ex) { | |
cout << ex.what() << "\n"; | |
} | |
cout << x << y << z << "\n"; | |
} |
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 <exception> | |
template <typename T> | |
class transacted { | |
public: | |
explicit transacted(T& t) | |
: copy_(t), original_(t), uncaughtExceptions_(std::uncaught_exceptions()) | |
{} | |
~transacted() | |
{ | |
if (uncaughtExceptions_ == std::uncaught_exceptions()) | |
commit(); | |
} | |
void commit() const | |
{ | |
original_ = copy_; | |
} | |
operator T&() { return copy_; } | |
operator const T&() const { return copy_; } | |
T& get() { return copy_; } | |
const T& get() const { return copy_; } | |
private: | |
T copy_; | |
T& original_; | |
int uncaughtExceptions_; | |
}; | |
#define TRANSACTED1(VAR1) auto& transacted_ref_ ## VAR1 = VAR1; transacted<decltype(VAR1)> VAR1{transacted_ref_ ## VAR1}; | |
#define TRANSACTED2(VAR1, VAR2) TRANSACTED1(VAR1) TRANSACTED1(VAR2) | |
#define TRANSACTED3(VAR1, VAR2, VAR3) TRANSACTED2(VAR1, VAR2) TRANSACTED1(VAR3) | |
#define TRANSACTED4(VAR1, VAR2, VAR3, VAR4) TRANSACTED2(VAR1, VAR2) TRANSACTED2(VAR3, VAR4) | |
#define TRANSACTED5(VAR1, VAR2, VAR3, VAR4, VAR5) TRANSACTED4(VAR1, VAR2, VAR3, VAR4) TRANSACTED1(VAR5) | |
#define EXPAND(x) x | |
#define GET_NTH_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N | |
#define VA_NUM_ARGS(...) EXPAND(GET_NTH_ARG(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)) | |
#define CONCATENATE(_1, _2) CONCATENATE_IMPL(_1, _2) | |
#define CONCATENATE_IMPL(_1, _2) _1##_2 | |
#define TRANSACTEDN(N, ...) CONCATENATE(TRANSACTED, N)(__VA_ARGS__) | |
#define TRANSACTED(...) TRANSACTEDN(VA_NUM_ARGS(__VA_ARGS__), __VA_ARGS__) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment