Last active
December 21, 2015 10:09
-
-
Save gintenlabo/6289916 to your computer and use it in GitHub Desktop.
bracket on C++11
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 <utility> | |
namespace etude { | |
namespace bracket_impl_ { | |
namespace here = bracket_impl_; | |
template<class T> | |
T& as_lvalue(T&& x) { | |
return x; | |
} | |
template<class F> | |
struct scope_guard { | |
explicit scope_guard(F f) | |
: f_(std::forward<F>(f)) { | |
} | |
~scope_guard() { | |
f_(); | |
} | |
// noncopyable | |
scope_guard(scope_guard &&) = delete; | |
void operator=(scope_guard&&) = delete; | |
private: | |
F f_; | |
}; | |
template<class Body, class Cleanup> | |
auto try_finally(Body&& body, Cleanup&& cleanup) | |
-> decltype(body()) { | |
scope_guard<Cleanup&> g(cleanup); | |
return body(); | |
} | |
template<class Acquire, class Release, class Action> | |
auto bracket(Acquire&& acquire, Release&& release, Action&& action) | |
-> decltype(action(here::as_lvalue(acquire()))) { | |
auto && r = acquire(); // resource | |
return here::try_finally( | |
[&] () -> decltype(action(r)) { | |
return action(r); | |
}, | |
[&] { | |
release(std::forward<decltype(r)>(r)); | |
} | |
); | |
} | |
template<class Before, class After, class Action> | |
auto bracket_(Before&& before, After&& after, Action&& action) | |
-> decltype(action()) { | |
before(); | |
return here::try_finally(action, after); | |
} | |
} // namespace bracket_impl_ | |
namespace bracket_adl_guard_ { | |
using bracket_impl_::try_finally; | |
using bracket_impl_::bracket; | |
using bracket_impl_::bracket_; | |
}// namespace bracket_adl_guard_ | |
using namespace bracket_adl_guard_; | |
} // namespace etude | |
#include <iostream> | |
#include <memory> | |
template<class T, class... Args> | |
std::unique_ptr<T> make_unique(Args&&... args) { | |
return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); | |
} | |
int main() { | |
etude::bracket_( | |
[] { | |
std::cout << "acquire some resources\n"; | |
}, | |
[] { | |
std::cout << "release resources\n"; | |
}, | |
[] { | |
std::cout << "do something with resources\n"; | |
} | |
); | |
try { | |
etude::bracket( | |
[] { | |
return make_unique<int>(42); | |
}, | |
[] (std::unique_ptr<int> p) { // moved | |
std::cout << "release\n"; | |
p.reset(); | |
}, | |
[] (std::unique_ptr<int> const& p) { // not moved | |
std::cout << *p << std::endl; | |
throw *p; | |
std::cout << "should not reach here.\n"; | |
} | |
); | |
} catch (int) { | |
// pass | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment