ラベル付きbreakが欲しい
他の多くの言語には、ラベル付きbreakがあるのに、C++にはない。
マクロで強引に実装してみた。
ついでに制御移行条件、制御移行前実行部も付けてみる。
#define CAT2(X,Y) X##Y #define XCAT(X,Y) X##Y #define CAT(X,Y) CAT2(X,Y) #define BRK CAT(BRK, __LINE__) #define CNT CAT(CNT, __LINE__) #define RDO CAT(RDO, __LINE__) #define BLABEL(lable) XCAT(BRK,lable) #define CLABEL(lable) XCAT(CNT,lable) #define RLABEL(lable) XCAT(RDO,lable) #define BREAK(cond, label) \ if(!((sizeof(#cond)==1)||bool(cond))) \ if(0){ CAT(NOLABEL,__LINE__): break; } else; \ else \ for(int CAT(LAST,__LINE__)=0;;++CAT(LAST,__LINE__)) \ if(CAT(LAST,__LINE__)) \ { goto BLABEL(label); BRK: goto CAT(NOLABEL,__LINE__); } \ else #define CONTINUE(cond, label) \ if(!((sizeof(#cond)==1)||bool(cond))) \ if(0){ CAT(NOLABEL,__LINE__): continue; } else; \ else \ for(int CAT(NEXT,__LINE__)=0;;++CAT(NEXT,__LINE__)) \ if(CAT(NEXT,__LINE__)) \ { goto CLABEL(label); CNT: goto CAT(NOLABEL,__LINE__); } \ else #if defined(__GNUC__) #define REDO(cond, label) \ if(!((sizeof(#cond)==1)||bool(cond))); \ else \ for(int CAT(REDO,__LINE__)=0;;++CAT((REDO,__LINE__)) \ if(CAT((REDO,__LINE__)) \ { goto RLABEL(label); RDO: goto *REDO; } \ else #else #define REDO(cond, label) \ if(!((sizeof(#cond)==1)||bool(cond))); \ else \ for(int CAT((REDO,__LINE__)=0;;++CAT((REDO,__LINE__)) \ if(CAT((REDO,__LINE__)) goto RLABEL(label); \ else #endif #if defined(__GNUC__) || defined(_MSC_VER) #define FOR(...) for(__VA_ARGS__) LABEL #define WHILE(...) while(__VA_ARGS__) LABEL #define DO do LABEL #else #define FOR(X) for (X) LABEL #define WHILE(X) while(X) LABEL #define DO do LABEL #endif #if defined(__GNUC__) #define LABEL(label) \ if(void*RE_DO=&&RLABEL(label)) \ { goto RLABEL(label); BLABEL(label): break; CLABEL(label):; } \ else RLABEL(label): #else #define LABEL(label) \ if(0) { BLABEL(label): break; CLABEL(label):; } else RLABEL(label): #endif
GCC以外に、VC,BCCでもある程度動く。条件部、ラベルはどちらも省略可能
使用例
// BREAKの動作確認。 puts("BREAKの動作確認"); FOR(i=1; i<=5; i++)(next1) { for(j=1; j<=3; j++) { printf("i=%d j=%d\n", i, j); BREAK(i+j >= 4, next1) // i+j >= 4 のとき、ループから脱出する。 puts("BREAK実行"); // ループから脱出する前にこの文を実行する。 } } puts(""); // CONTINUEの動作確認。 puts("CONTINUEの動作確認"); FOR(i=1; i<=5; i++)(next2) { for(j=1; j<=3; j++) { printf("i=%d j=%d\n", i, j); CONTINUE(i+j >= 4, next2) puts("CONTINUE実行"); } }