#include <iostream>
#include <string>
#include <exception>
#include <stdexcept>
using namespace std;


template<class F> class ScopeGuard
{
private:
	F f;
	bool active;
public:
	ScopeGuard(F f) :f(::std::move(f)), active(true) {}
	ScopeGuard(ScopeGuard&& rhs) :f(::std::move(rhs.f)), active(rhs.active) { rhs.dismiss();}
	~ScopeGuard() { if (active) f(); }

	void dismiss() { active = false; }

	ScopeGuard() = delete;
	ScopeGuard(const ScopeGuard&) = delete;
	ScopeGuard& operator=(const ScopeGuard&) = delete;
};

template<class FF> static ScopeGuard<FF> makeScopeGuard(FF f) { return ScopeGuard<FF>(f); }

#define CONCAT_IMPL(s1, s2) s1##s2
#define CONCAT(s1, s2) CONCAT_IMPL(s1, s2)

#define SCOPE_GUARD(lambda) \
  auto CONCAT(scope_guard_, __LINE__)(makeScopeGuard(lambda)); \
  (void)CONCAT(scope_guard_, __LINE__);


void scopeExit(const string& name)
{
	cout << "Exiting " << name << " scope "
	     << (uncaught_exception() ? "(there was an exception)" : "(no exception)") << endl;
}

int main()
{
	SCOPE_GUARD([](){ scopeExit("main"); })

	try
	{
		SCOPE_GUARD([](){ scopeExit("try"); })
		throw runtime_error("Spectacular failure!");
	}
	catch (const exception& e)
	{
		cout << e.what() << endl;
	}

	return 0;
}
