スポンサーリンク
C言語系の関数は例外に対応していない。
個人的に例外は機能は好きだが構文は嫌いだ。それでも使った方がすっきりかける場合もある。
一番簡単なのはラップしてしまう事だろうがつまらないのでもうちょっと自己満足のいくものを考える。
以下のようなクラスを作る。(改めてみるとクラス名がひどい)
template<typename T> class MakeThrow{ T verr; int err_id; public: void ErrorValue(const T val){ verr = val; } void operator=(const T& v){ if( v == verr){ throw err_id; } }; MakeThrow<T>& operator()(const int id){ err_id=id; return *this; } };
そして以下のように使う
int _tmain(int argc, _TCHAR* argv[]) { MakeThrow<FILE*> rets; rets.ErrorValue(nullptr); try{ rets(5) = fopen("abc","r"); } catch(int e){ std::cout << e; } getchar(); return 0; }
retsの=をオーバーロードし、C言語系の関数の戻り値を受け取れるようにする。
=の中では、受け取った値を比較し、エラー値なら例外を出す。この時エラー番号を投げておくと、どこでエラーがあったかがよりわかりやすくなる(多分)ので、operator()でエラー番号を指定すると、その数値をcatchすることができる。
まあ、普通はまず使わないだろうが、XmlLite プログラミングを読んでいると、命令の一つ一つでif(FAILED(...)を行っていて、たとえそれが合理的で完膚なきまでに正しい行為でも、もう少し何とかならんのかと思ってしまったのである。
if(FAILED(pWriter->WriteStartElement(NULL, L"requirement", NULL))){ MessageBox(NULL, _T("WriteStartElement失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } if(FAILED(pWriter->WriteElementString(NULL, L"type", NULL, L"ヘッダ"))){ MessageBox(NULL, _T("WriteElementString失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } if(FAILED(pWriter->WriteElementString(NULL, L"name", NULL, L"XmlLite.h"))){ MessageBox(NULL, _T("WriteElementString失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; } if(FAILED(pWriter->WriteFullEndElement())){ MessageBox(NULL, _T("WriteFullEndElement失敗"), _T("警告"), MB_OK | MB_ICONWARNING); return; }