とくにあぶなくないRiSKのブログ

危ないRiSKのブログだったかもしれない。本当はRiSKだけどググラビリティとか取得できるIDの都合でsscriskも使ったり。

C言語でtry-catch-finaly

というわけで,某CotNet Framework で使われるかもしれない TryCatch.h をごらんあれ。
MFCは軽く凌駕してるはずです。FINALLYなんて C/C++ らしからぬものまであるし。

/*! \file TryCatch.h
 *  \brief TRY-CATCH-FINALLY macros.
 *  \author RiSK
 *  \since 20070509
 */

#include <TryCatch/ExceptionStack.h>
#include <TryCatch/JBStack.h>

/*! 例外を投げます。Exceptionクラスの派生クラスを渡します。 */
#define THROW(NEW_EXCEPTION)				\
do							\
{							\
     ExceptionStack_Push((Exception)NEW_EXCEPTION);	\
     longjmp(JBStack_Peek(), 1);			\
}							\
while(0)

/*! エラーが発生する可能性のあるコードを書きます。
 *  TRYブロックの後ろにはCATCHブロック
 *  またはFANALLYブロックが続きます。
 */
#define TRY					\
{						\
     jmp_buf*jb = malloc(sizeof(jmp_buf));	\
     if (!setjmp(*jb))				\
     {						\
	  JBStack_Push(jb);			\
	  {

/*! 例外を捕まえます。
 *  CATCHブロック,FINALLYブロックまたはEND_CATCHが続きます。
 *  \param[in] EXCEPTION_CLASS 捕まえたいExceptionの派生クラス
 *  \param[in] EXCEPTION_IDENTIFIER 利用するEXCEPTION_CLASSの識別子
 */
#defne CATCH(EXCEPTION_CLASS, EXCEPTION_IDENTIFIER)			\
	  }								\
	  goto finally;							\
     } while (0);							\
     do	{								\
	  EXCEPTION_CLASS EXCEPTION_IDENTIFIER = new_#EXCEPTION_CLASS(); \
	  if (!IsFamily(ExceptionStack_Peek(), EXCEPTION_IDENTIFIER))	\
	  {								\
	       break;							\
	  }								\
	  {

/*! TRYブロックまたはCATCHブロックの後に実行されます。 */
#define FINALLY					\
	  }					\
     } while (0);				\
     {						\
	  THROW(ExceptionStack_Pop());		\
     }						\
finally:					\
     free(JBStack_Pop());			\
}

/*! FINALLYが必要ないときにCATCHブロックのあとに実行されます。 */
#define END_CATCH FINALLY

普通にTRY{}CATCH{}FINALLY{}ってできるはずだし,CATCHを抜いてTRY{}FINALLY{}ともできるはずだし,TRY{}CATCH{}END_CATCH; hoge;ともできるはず。私の脳内では。while(0); がかなりトリッキーだとおもふ。
これぐらいやればコード芸人を自負していいでしょか>id:Ozyさん