実際、関数を終了するために何らかのコードを実行する必要があることが頻繁に発生し、毎回ガードを作成するのは面倒であり、常に可能ではありません。
しかし、新しい標準を使用すると、C ++では、誰も気にしないでください-猫の下で、悪化させることはできません。
アイデア自体は非常に単純です。コンストラクターでファンクターを取り、デストラクターで実行するクラスを作成する必要があります。
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_; };
次のように書くことができます:
int test() { std::string omega; std::cin >> omega; exit_scope guard1 = [&](){ std::cout<< "First exit scope "<<omega<<std::endl; }; return 0; }
まだあまり便利ではありません。
Habréでのマクロの週以来、マクロの使用を簡素化しようとしています。
#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__) = [&]()
これで、コードで次のように記述できます。
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; }
私の意見では-はるかに良い。
しかし、クラス自体はあまり良くありません。std::関数を使用して組み合わせてみてください。
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_; };
ブースト(または、むしろブーストで標準になったもの)について話しているので、同様のメカニズムがあることに言及せざるを得ません。 しかし、彼は新しい標準を利用しておらず、私の好みのためにそれを使用することは完全に便利ではありません。
boost / scope_exit.hppを使用すると、次のようなコードを記述できます。
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; }
私の実装の欠点の中で、特定の実行見出しと、呼び出されたコードの実行に関する問題に名前を付けることができます。