Last active
August 29, 2015 14:21
-
-
Save elbeno/33881ff770805d8375d2 to your computer and use it in GitHub Desktop.
WITH macro for C++
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 <algorithm> | |
#include <cassert> | |
#include <utility> | |
#include <iostream> | |
using namespace std; | |
class Light | |
{ | |
public: | |
void turn_on() { m_on = true; }; | |
void turn_off() { m_on = false; } | |
bool is_on() const { return m_on; } | |
private: | |
bool m_on = false; | |
}; | |
class LightGuard | |
{ | |
public: | |
explicit LightGuard(Light& l) : m_light{&l} { m_light->turn_on(); } | |
~LightGuard() { if(m_light) m_light->turn_off(); } | |
LightGuard(LightGuard&& rhs) : m_light{std::move(rhs.m_light)} { rhs.m_light = nullptr; } | |
LightGuard& operator=(LightGuard&& rhs) | |
{ | |
std::swap(m_light, rhs.m_light); | |
return *this; | |
} | |
LightGuard(const LightGuard& rhs) = delete; | |
LightGuard& operator=(LightGuard& rhs) = delete; | |
private: | |
Light* m_light = nullptr; | |
}; | |
template <typename T> | |
struct always_true | |
{ | |
explicit always_true(T what) : x{std::move(what)} {} | |
always_true(always_true&& other) : x{std::move(other.x)} {} | |
constexpr operator bool() const { return true; } | |
T x; | |
}; | |
template <typename T> | |
auto make_true(T&& what) -> always_true<T> | |
{ | |
static_assert(std::is_move_constructible<T>::value, | |
"make_true argument must be move constructible"); | |
return always_true<T>{std::forward<T>(what)}; | |
} | |
#define WITH(what) \ | |
if (auto with_always_true = make_true(what)) | |
Light the_light; | |
void prepare_drinks() | |
{ | |
if (the_light.is_on()) | |
cout << "Preparing drinks" << endl; | |
} | |
void watch_movie() | |
{ | |
if (!the_light.is_on()) | |
cout << "Watching movie" << endl; | |
} | |
int main() | |
{ | |
WITH(LightGuard{the_light}) | |
{ | |
assert(the_light.is_on()); | |
prepare_drinks(); | |
} | |
assert(!the_light.is_on()); | |
watch_movie(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment