Created
June 10, 2015 08:34
-
-
Save C0deH4cker/cbb972d2b360647ab5ed to your computer and use it in GitHub Desktop.
Python's with statement, implemented in C++ via macros
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
// Just like C#'s using statement and Python's with statement. | |
// This allows use of a resource within a code block, after which | |
// the declared object's destructor will clean up. | |
// There's nothing about `with` that doesn't work in C, but it is | |
// pointless in standard C as there are no destructors. | |
// Multiple with statements can be nested as well, so it works as | |
// you'd expect. If for some bizarre reason you need to put multiple | |
// using statements on the same line, I've added another version, | |
// defined below as with_inline. | |
// | |
// Example: | |
// | |
// void runOnlyTenTimes() { | |
// static std::mutex runCountMutex; | |
// static int timesRun = 0; | |
// | |
// with (std::lock_guard<std::mutex> lock(runCountMutex)) { | |
// if(timesRun == 10) { | |
// return; | |
// } | |
// | |
// ++timesRun; | |
// } | |
// | |
// actuallyRun(); | |
// } | |
#define with(...) _with(__LINE__, __VA_ARGS__) | |
#define _with(id, ...) __with(id, __VA_ARGS__) | |
#define __with(id, ...) \ | |
for(int _with_##id = 1; _with_##id; _with_##id = 0) \ | |
for(__VA_ARGS__; _with_##id; _with_##id = 0) | |
// Same as with, except this version works even when multiple with | |
// statements are used on the same line (probably ugly code though) | |
#define with_inline(...) _with(__COUNTER__, __VA_ARGS__) |
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
#include "with.h" | |
#include <iostream> | |
using namespace std; | |
struct A { | |
int val; | |
A(int x): val(x) { | |
cout << "A(" << val << ") constructed!" << endl; | |
} | |
virtual ~A() { | |
cout << "A(" << val << ") destroyed!" << endl; | |
} | |
}; | |
struct B: public A { | |
B(int x): A(x) { | |
cout << "B(" << val << ") constructed!" << endl; | |
} | |
virtual ~B() { | |
cout << "B(" << val << ") destroyed!" << endl; | |
} | |
}; | |
int main() { | |
cout << "In main()" << endl; | |
with(A a1(42), a2(69)) { | |
cout << "In with body" << endl; | |
} | |
cout << "Between with statements" << endl; | |
with_inline(A a(1337)) with_inline(B b(31337)) { | |
cout << "In with_inline body" << endl; | |
} | |
cout << "Returning from main()" << endl; | |
return 0; | |
} | |
/* | |
Output: | |
In main() | |
A(42) constructed! | |
A(69) constructed! | |
In with body | |
A(69) destroyed! | |
A(42) destroyed! | |
Between with statements | |
A(1337) constructed! | |
A(31337) constructed! | |
B(31337) constructed! | |
In with_inline body | |
B(31337) destroyed! | |
A(31337) destroyed! | |
A(1337) destroyed! | |
Returning from main() | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment