#include <functional>
template<class functionoid>
class finally_type {
public:
template<class functionoid0>
finally_type(functionoid0&& f) :func(std::forward<functionoid0>(f)) {}
finally_type(finally_type&& rhs) :func(std::move(rhs.func)) {}
finally_type(const finally_type& rhs) :func(rhs.func) {}
finally_type& operator=(finally_type&& rhs) {func=std::move(rhs.func); return *this;}
finally_type& operator=(const finally_type& rhs) {func=rhs.func; return *this;}
~finally_type() {func();}
private:
functionoid func;
};
template<class functionoid>
inline finally_type<functionoid> finally(functionoid&& func)
{return finally_type<functionoid>(std::forward<functionoid>(func));}
template<class functionoid, class T0>
inline auto finally(functionoid&& func, T0&& p0)
->decltype(finally(std::bind(std::forward<functionoid>(func), std::forward<T0>(p0))))
{return finally(std::bind(std::forward<functionoid>(func), std::forward<T0>(p0)));}
template<class functionoid, class T0, class T1>
inline auto finally(functionoid&& func, T0&& p0, T1&& p1)
->decltype(finally(std::bind(std::forward<functionoid>(func), std::forward<T0>(p0), std::forward<T1>(p1))))
{return finally(std::bind(std::forward<functionoid>(func), std::forward<T0>(p0), std::forward<T1>(p1)));}
template<class functionoid, class T0, class T1, class T2>
inline auto finally(functionoid&& func, T0&& p0, T1&& p1, T2&& p2)
->decltype(finally(std::bind(std::forward<functionoid>(func), std::forward<T0>(p0), std::forward<T1>(p1), std::forward<T2>(p2))))
{return finally(std::bind(std::forward<functionoid>(func), std::forward<T0>(p0), std::forward<T1>(p1), std::forward<T2>(p2)));}
template<class functionoid, class T0, class T1, class T2, class T3>
inline auto finally(functionoid&& func, T0&& p0, T1&& p1, T2&& p2, T3&& p3)
->decltype(finally(std::bind(std::forward<functionoid>(func), std::forward<T0>(p0), std::forward<T1>(p1), std::forward<T2>(p2), std::forward<T3>(p3))))
{return finally(std::bind(std::forward<functionoid>(func), std::forward<T0>(p0), std::forward<T1>(p1), std::forward<T2>(p2), std::forward<T2>(p3)));}
#include <iostream>
int print(int i)
{
std::cout << i << ' ';
return i;
}
int main() {
auto f = finally(print, 13);
return print(0);
}
I2luY2x1ZGUgPGZ1bmN0aW9uYWw+Cgp0ZW1wbGF0ZTxjbGFzcyBmdW5jdGlvbm9pZD4KY2xhc3MgZmluYWxseV90eXBlIHsKcHVibGljOgogICAgdGVtcGxhdGU8Y2xhc3MgZnVuY3Rpb25vaWQwPgogICAgZmluYWxseV90eXBlKGZ1bmN0aW9ub2lkMCYmIGYpIDpmdW5jKHN0ZDo6Zm9yd2FyZDxmdW5jdGlvbm9pZDA+KGYpKSB7fQogICAgZmluYWxseV90eXBlKGZpbmFsbHlfdHlwZSYmIHJocykgOmZ1bmMoc3RkOjptb3ZlKHJocy5mdW5jKSkge30KICAgIGZpbmFsbHlfdHlwZShjb25zdCBmaW5hbGx5X3R5cGUmIHJocykgOmZ1bmMocmhzLmZ1bmMpIHt9CiAgICBmaW5hbGx5X3R5cGUmIG9wZXJhdG9yPShmaW5hbGx5X3R5cGUmJiByaHMpIHtmdW5jPXN0ZDo6bW92ZShyaHMuZnVuYyk7IHJldHVybiAqdGhpczt9CiAgICBmaW5hbGx5X3R5cGUmIG9wZXJhdG9yPShjb25zdCBmaW5hbGx5X3R5cGUmIHJocykge2Z1bmM9cmhzLmZ1bmM7IHJldHVybiAqdGhpczt9CiAgICB+ZmluYWxseV90eXBlKCkge2Z1bmMoKTt9CnByaXZhdGU6CiAgICBmdW5jdGlvbm9pZCBmdW5jOwp9Owp0ZW1wbGF0ZTxjbGFzcyBmdW5jdGlvbm9pZD4KaW5saW5lIGZpbmFsbHlfdHlwZTxmdW5jdGlvbm9pZD4gZmluYWxseShmdW5jdGlvbm9pZCYmIGZ1bmMpIAp7cmV0dXJuIGZpbmFsbHlfdHlwZTxmdW5jdGlvbm9pZD4oc3RkOjpmb3J3YXJkPGZ1bmN0aW9ub2lkPihmdW5jKSk7fQp0ZW1wbGF0ZTxjbGFzcyBmdW5jdGlvbm9pZCwgY2xhc3MgVDA+CmlubGluZSBhdXRvIGZpbmFsbHkoZnVuY3Rpb25vaWQmJiBmdW5jLCBUMCYmIHAwKSAKICAgIC0+ZGVjbHR5cGUoZmluYWxseShzdGQ6OmJpbmQoc3RkOjpmb3J3YXJkPGZ1bmN0aW9ub2lkPihmdW5jKSwgc3RkOjpmb3J3YXJkPFQwPihwMCkpKSkgCntyZXR1cm4gZmluYWxseShzdGQ6OmJpbmQoc3RkOjpmb3J3YXJkPGZ1bmN0aW9ub2lkPihmdW5jKSwgc3RkOjpmb3J3YXJkPFQwPihwMCkpKTt9CnRlbXBsYXRlPGNsYXNzIGZ1bmN0aW9ub2lkLCBjbGFzcyBUMCwgY2xhc3MgVDE+CmlubGluZSBhdXRvIGZpbmFsbHkoZnVuY3Rpb25vaWQmJiBmdW5jLCBUMCYmIHAwLCBUMSYmIHAxKSAKICAgIC0+ZGVjbHR5cGUoZmluYWxseShzdGQ6OmJpbmQoc3RkOjpmb3J3YXJkPGZ1bmN0aW9ub2lkPihmdW5jKSwgc3RkOjpmb3J3YXJkPFQwPihwMCksIHN0ZDo6Zm9yd2FyZDxUMT4ocDEpKSkpIAp7cmV0dXJuIGZpbmFsbHkoc3RkOjpiaW5kKHN0ZDo6Zm9yd2FyZDxmdW5jdGlvbm9pZD4oZnVuYyksIHN0ZDo6Zm9yd2FyZDxUMD4ocDApLCBzdGQ6OmZvcndhcmQ8VDE+KHAxKSkpO30KdGVtcGxhdGU8Y2xhc3MgZnVuY3Rpb25vaWQsIGNsYXNzIFQwLCBjbGFzcyBUMSwgY2xhc3MgVDI+CmlubGluZSBhdXRvIGZpbmFsbHkoZnVuY3Rpb25vaWQmJiBmdW5jLCBUMCYmIHAwLCBUMSYmIHAxLCBUMiYmIHAyKSAKICAgIC0+ZGVjbHR5cGUoZmluYWxseShzdGQ6OmJpbmQoc3RkOjpmb3J3YXJkPGZ1bmN0aW9ub2lkPihmdW5jKSwgc3RkOjpmb3J3YXJkPFQwPihwMCksIHN0ZDo6Zm9yd2FyZDxUMT4ocDEpLCBzdGQ6OmZvcndhcmQ8VDI+KHAyKSkpKSAKe3JldHVybiBmaW5hbGx5KHN0ZDo6YmluZChzdGQ6OmZvcndhcmQ8ZnVuY3Rpb25vaWQ+KGZ1bmMpLCBzdGQ6OmZvcndhcmQ8VDA+KHAwKSwgc3RkOjpmb3J3YXJkPFQxPihwMSksIHN0ZDo6Zm9yd2FyZDxUMj4ocDIpKSk7fQp0ZW1wbGF0ZTxjbGFzcyBmdW5jdGlvbm9pZCwgY2xhc3MgVDAsIGNsYXNzIFQxLCBjbGFzcyBUMiwgY2xhc3MgVDM+CmlubGluZSBhdXRvIGZpbmFsbHkoZnVuY3Rpb25vaWQmJiBmdW5jLCBUMCYmIHAwLCBUMSYmIHAxLCBUMiYmIHAyLCBUMyYmIHAzKSAKICAgIC0+ZGVjbHR5cGUoZmluYWxseShzdGQ6OmJpbmQoc3RkOjpmb3J3YXJkPGZ1bmN0aW9ub2lkPihmdW5jKSwgc3RkOjpmb3J3YXJkPFQwPihwMCksIHN0ZDo6Zm9yd2FyZDxUMT4ocDEpLCBzdGQ6OmZvcndhcmQ8VDI+KHAyKSwgc3RkOjpmb3J3YXJkPFQzPihwMykpKSkgCntyZXR1cm4gZmluYWxseShzdGQ6OmJpbmQoc3RkOjpmb3J3YXJkPGZ1bmN0aW9ub2lkPihmdW5jKSwgc3RkOjpmb3J3YXJkPFQwPihwMCksIHN0ZDo6Zm9yd2FyZDxUMT4ocDEpLCBzdGQ6OmZvcndhcmQ8VDI+KHAyKSwgc3RkOjpmb3J3YXJkPFQyPihwMykpKTt9CgoKCgoKCgoKCiNpbmNsdWRlIDxpb3N0cmVhbT4KaW50IHByaW50KGludCBpKQp7CiAgICBzdGQ6OmNvdXQgPDwgaSA8PCAnICc7IAogICAgcmV0dXJuIGk7Cn0KCmludCBtYWluKCkgewogICAgYXV0byBmID0gZmluYWxseShwcmludCwgMTMpOwogICAgcmV0dXJuIHByaW50KDApOwp9