サンプルの動作確認バージョン [GCC4.4/1.41.0] [VC9/1.41.0]
#include <iostream>
#include <vector>
#include <numeric>
#include <boost/foreach.hpp>
#include <boost/scope_exit.hpp>
using namespace std;
void f( vector<int>& v1, vector<int>& v2 )
{
// v1 に 値を push
v1.push_back(v1.size());
// f を抜けるときに戻す
BOOST_SCOPE_EXIT( (&v1) )
{
v1.pop_back();
}
BOOST_SCOPE_EXIT_END
// v2 に 値を push
v2.push_back(v2.size());
// f を抜けるときに戻す
BOOST_SCOPE_EXIT( (&v2) )
{
v2.pop_back();
}
BOOST_SCOPE_EXIT_END
// 適当になにか処理
if( accumulate(v1.begin(), v1.end(), 0) > 10 )
throw "exception-1!";
if( accumulate(v2.begin(), v2.end(), 0) > 10 )
throw "exception-2!";
cout << "ok" << endl;
}
int main()
{
vector<int> v1; v1.push_back(1); v1.push_back(2);
vector<int> v2; v2.push_back(3); v2.push_back(4);
try { f(v1, v2); } catch(const char* e) {cout << e << endl;}
BOOST_FOREACH(int a, v1) { cout << a << " "; } cout << endl;
BOOST_FOREACH(int a, v2) { cout << a << " "; } cout << endl;
v1.push_back(0);
v2.push_back(1);
try { f(v1, v2); } catch(const char* e) {cout << e << endl;}
BOOST_FOREACH(int a, v1) { cout << a << " "; } cout << endl;
BOOST_FOREACH(int a, v2) { cout << a << " "; } cout << endl;
}
ちょっと人工的な例ですが…
ok 1 2 3 4 exception-2! 1 2 0 3 4 1
2回目は、3+4+1+3が10を越えるので例外が飛んでいますが、fから例外で戻ってくるときにはf内でpushした 3はちゃんとpopされていて、表示は3 4 1になっています。
いわゆる try~catch~finally の finally というか、 D言語のscope(exit)文 のC++によるライブラリ実装です。 例外で抜けるかreturnやその他正常終了で抜けるかに関わらず、 スコープの終わりに必ず実行したい処理(リソースの後始末等)を書くことができます。 公式ドキュメントの Alternatives や、D言語リファレンスの 例外安全なプログラミング で、finally や RAII などの近い言語機能との比較がなされています。