Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
class call_func_when_out_of_scope {
public:
call_func_when_out_of_scope(boost::function<void()> func_to_call_in_destructor)
: f(func_to_call_in_destructor)
{}
~call_func_when_out_of_scope() {
if (!f.empty())
f();
}
protected:
boost::function<void()> f;
};
void test(int i)
{
printf("in test, i=%d!\n", i);
}
int main()
{
call_func_when_out_of_scope h(boost::bind(test, 42));
printf("out of main()!\n");
return 0;
}
/* Output:
out of main()!
in test, i=42!
*/
{
...
if (FILE* f = fopen("foo_bar.data", "r")) {
call_func_when_out_of_scope close_file(boost::bind(fclose, f));
....
}
}
// module 1
void fun()
{
}
struct str
{
void operator()() {}
};
std::function<void()> f1 = fun;
std::function<void()> f2 = str();
// module 2
f1();
f2();
call_func_when_out_of_scope h2([]() {
printf("in inner lambda\n");
});
template<typename F>
class ScopeExit
{
public:
ScopeExit(const F& fn) : m_fn(fn) {;}
~ScopeExit()
{
m_fn();
}
private:
F m_fn;
};
template<typename F>
ScopeExit<F> CreateScopeExit(F fn)
{
return ScopeExit<F>(fn);
}
#define EXIT_SCOPE_CREATE_UNIQ_NAME2(line) exit_scope_guard_##line
#define EXIT_SCOPE_CREATE_UNIQ_NAME(line) EXIT_SCOPE_CREATE_UNIQ_NAME2(line)
#define EXIT_SCOPE(F) const auto &EXIT_SCOPE_CREATE_UNIQ_NAME(__LINE__) = CreateScopeExit([]{F;})
int main()
{
std::cout << "Outer scope enter" << std::endl;
EXIT_SCOPE(std::cout << "Outer scope exited" << std::endl);
{
std::cout << "Inner scope enter" << std::endl;
EXIT_SCOPE({std::cout << "Inner scope exited" << std::endl;});
std::cout << "Inner scope exit" << std::endl;
}
std::cout << "Outer scope exit" << std::endl;
return 0;
}
class ScopeExitCreator
{
public:
template<typename Fn>
ScopeExit<Fn> operator << (const Fn &fn)
{
return ScopeExit<Fn>(fn);
}
};
#define EXIT_SCOPE_CREATE_UNIQ_NAME2(line) exit_scope_guard_##line
#define EXIT_SCOPE_CREATE_UNIQ_NAME(line) EXIT_SCOPE_CREATE_UNIQ_NAME2(line)
#define EXIT_SCOPE const auto &EXIT_SCOPE_CREATE_UNIQ_NAME(__LINE__) = ScopeExitCreator() << [&]()
int main()
{
std::cout << "Outer scope enter" << std::endl;
EXIT_SCOPE{std::cout << "Outer scope exited" << std::endl;};
{
std::cout << "Inner scope enter" << std::endl;
EXIT_SCOPE{std::cout << "Inner scope exited" << std::endl;};
std::cout << "Inner scope exit" << std::endl;
}
std::cout << "Outer scope exit" << std::endl;
return 0;
}
int test1()
{
std::string omega = "very big string"; // throw bad_alloc, EXIT_SCOPE не выполнится
if (omega.empty())
{
return -1; //EXIT_SCOPE не выполнится, это как минимум не очевидно
}
std::cin >> omega;
EXIT_SCOPE{ std::cout << "Second exit scope" << omega<< std::endl; };
EXIT_SCOPE{ std::cout << "Third exit scope" << omega<<std::endl; };
return 0;
}
int test1()
{
std::string omega;
std::cin >> omega;
EXIT_SCOPE{ std::cout << "Second exit scope" << omega<< std::endl; };
EXIT_SCOPE{ std::cout << "Third exit scope" << omega<<std::endl; };
return 0;
}
int test1()
{
std::string omega;
std::cin >> omega;
std::cout << "Second exit scope" << omega<< std::endl;;
std::cout << "Third exit scope" << omega<<std::endl;;
return 0;
}
int test1()
{
std::string omega;
EXIT_SCOPE{ std::cout << "Second exit scope" << omega<< std::endl; };
EXIT_SCOPE{ std::cout << "Third exit scope" << omega<<std::endl; };
std::cin >> omega; // can throw an exception
omega += " super puper omega"; // throw bad_alloc()
//и еще куча кода
if (omega.empty())
{
return -1;
}
return 0;
}
int test1()
{
std::string omega;
std::cin >> omega; // can throw an exception
omega += " super puper omega"; // throw bad_alloc()
//и еще куча кода
if (omega.empty())
{
return -1;
}
std::string alpha;
std::cin >> alpha;
EXIT_SCOPE{ std::cout << "Second exit scope" << omega << alpha << std::endl; };
EXIT_SCOPE{ std::cout << "Third exit scope" << omega<< alpha << std::endl; };
return 0;
}
exit_scope guard1([&]() {
std::cout<< "First exit scope " << omega << std::endl;
});
Аналог scope(exit) на С++