📜 ⬆️ ⬇️

Analogue scope (exit) in C ++

I read recently, in Habré, an article about scope (exit) in the D language and imbued with the beauty of the idea.
After all, it often happens that you need to execute any code to exit a function, and it’s tiring to create a guard every time, and it’s not always possible.
But, using a new standard, in C ++ you can do no worse, for whom it is interesting - please under the cat.

The idea itself is very simple; you need to create a class that accepts a functor in the constructor and executes it in the destructor.
class exit_scope { public: template< typename Callback > exit_scope( const Callback& callback ):caller_( new caller<Callback>(callback) ){} ~exit_scope(){ caller_->call(); delete caller_; } private: exit_scope(); exit_scope(const exit_scope&); exit_scope& operator =(const exit_scope&); struct caller_interface { virtual ~caller_interface(){} virtual void call()=0; }; template< typename Callback > struct caller: caller_interface { caller( const Callback& callback ): callback_(callback){} virtual void call(){ callback_(); } Callback callback_; }; caller_interface* caller_; }; 

Now you can write something like:
 int test() { std::string omega; std::cin >> omega; exit_scope guard1 = [&](){ std::cout<< "First exit scope "<<omega<<std::endl; }; return 0; } 

Not very convenient yet.
Since there is a week of macros in Habré, let's try to simplify use with the help of them:
 #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 exit_scope EXIT_SCOPE_CREATE_UNIQ_NAME(__LINE__) = [&]() 

Now in the code you can write like this:
 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; } 

In my opinion - much better.
That's just the class itself does not look very, try to comb it using std :: function.
 class exit_scope { public: template< typename Callback > exit_scope( const Callback& callback ):callback_(callback){} ~exit_scope(){ callback_(); } private: exit_scope(); exit_scope(const exit_scope&); exit_scope& operator =(const exit_scope&); std::function<void(void)> callback_; }; 

Since we are talking about the boost (or rather, what came to it from the standard), it is impossible not to mention that there is a similar mechanism in it. But he does not take advantage of the new standard, and using it, for my taste, is not very convenient.
Using boost / scope_exit.hpp, you could write code like this:
 int test1() { std::string omega; std::cin >> omega; BOOST_SCOPE_EXIT( (&omega) ) { std::cout << "Fourth exit scope" <<omega<< std::endl; } BOOST_SCOPE_EXIT_END return 0; } 

From the shortcomings of my implementation, we can call some overhead to execute and a problem with exceptions in the called code.

')

Source: https://habr.com/ru/post/148534/


All Articles