▌第一次閱讀本系列的,可以先看:
▌第一次閱讀例外處理系列,可以先看:
前一篇文章有核心代碼,製成標頭檔載入,
【實驗性質】,隨便玩玩,小心使用。
【實驗性質】,隨便玩玩,小心使用。
▌可使用的巨集函數:
throw
clear_throw
check
try
catch_start
catch
finally
catch_end
共有 8 個,使用次序由上至下。
throw
clear_throw
check
try
catch_start
catch
finally
catch_end
共有 8 個,使用次序由上至下。
▌具體巨集函數的使用方式:
純粹介紹使用方式,具體原理不說,由上至下介紹。
/*throw*/
#define throw(ex_name, ...) \
\
setter_error_code(#ex_name); \
return __VA_ARGS__;
throw(拋出的錯誤名稱 [, 回傳值]);
於發生錯誤處使用,可指定拋出的錯誤名稱,
需指定拋出錯誤的函數返回的值,若函數的返回類型為 void
,第二項參數不需輸入。
/*clear_throw*/
#define clear_throw() \
\
setter_error_code("");
無參數,調用後清除拋出的錯誤,用於忽略錯誤。
若果拋出錯誤後不處理,又沒有調用 clear_throw
,
有機會給 check
所意外捕捉。
這是因為拋出的錯誤是以殘留的方式存在,
殘留直至捕捉處理。
/*check*/
#define check(...) \
\
if(strcmp(getter_error_code(), "")){ \
return __VA_ARGS__; \
}
捕捉/檢測有否拋出錯誤/發生錯誤。
若是,函數返回。(回到上一層)
基於拋出的錯誤是以殘留的方式存在,等價拋出錯誤。
同樣需指定返回的值,若函數的返回類型為 void
,不需輸入。
/*try$*/
#define try$(back_point, args) \
\
if(strcmp(getter_error_code(), "")){ \
setter_back_point(#back_point); \
if(strcmp(args, "")) \
setter_error_code(args); \
goto catch_start;\
} \
back_point:
/*try*/
#define try(back_point, ...) try$(back_point, "" #__VA_ARGS__)
try(返回點 [, 自行指定錯誤名稱])
必須指定返回點,返回點由 catch_end
檢測,並返回對應 try
的返回點。
若第二項參數不輸入,默認使用 throw
所拋出的錯誤名稱。
若輸入第二項參數,可自行指定錯誤名稱。
自行指定錯誤名稱用於區分拋出相同錯誤但又需要不同處理的函數。
/*catch_start*/
#define catch_start(...) \
\
catch_start: \
if(!strcmp(getter_error_code(), "")) return __VA_ARGS__;
每一個 try
檢測到錯誤後都會到達 catch_start
點,
一個參數,用於 正常(沒有發生錯誤)到達 catch_start
處時 指定返回的值,
同樣,若函數的返回類型為 void
,不需輸入。
可順便代替函數末端的 return
。
/*catch*/
#define catch(ex_name) \
\
if(!strcmp(getter_error_code(), #ex_name))
catch(錯誤名稱)
捕捉錯誤,發現對應的錯誤名稱時,運行對應區塊的代碼。
/*finally*/
#define finally()
完全空白的裝飾巨集,沒有實際工作。
因為在 catch_start
到 catch_end
的區間中,
沒有被 catch
包括的都會被直接運行,
所以 finally
是用於增加可讀性,給開發者看的。
/*back*/
#define back(back_point) \
\
if(!strcmp(getter_back_point(), #back_point)){ \
goto back_point; \
}
/*get_11th_arg*/
#define get_11th_arg(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, arg11, ...) arg11
/*magic_bracket*/
#define magic_bracket(...) (__VA_ARGS__)
#define magic_left_bracket(...) (__VA_ARGS__
/*back2 - 10*/
#define back2(arg2, arg1) back(arg2) back(arg1) printf("[Error] 沒有透過 try 進入 catch / 找不到相應的返回點");
#define back3(arg3, ...) back(arg3) back2 magic_bracket(__VA_ARGS__)
#define back4(arg4, ...) back(arg4) back3 magic_bracket(__VA_ARGS__)
#define back5(arg5, ...) back(arg5) back4 magic_bracket(__VA_ARGS__)
#define back6(arg6, ...) back(arg6) back5 magic_bracket(__VA_ARGS__)
#define back7(arg7, ...) back(arg7) back6 magic_bracket(__VA_ARGS__)
#define back8(arg8, ...) back(arg8) back7 magic_bracket(__VA_ARGS__)
#define back9(arg9, ...) back(arg9) back8 magic_bracket(__VA_ARGS__)
#define back10(arg10, ...) back(arg10) back9 magic_bracket(__VA_ARGS__)
/*back_list 10-1*/
#define back_list back10, back9, back8, back7, back6, back5, back4, back3, back2, back
/*catch_end*/
#define catch_end(...) \
\
setter_error_code(""); \
get_11th_arg magic_left_bracket(__VA_ARGS__), back_list) (__VA_ARGS__)
不需要理會內部具體運作,
catch_end(...)
擁有上限為十的可變參數,會清除/重置殘留的錯誤。
參數為返回點,調用時會檢測所有輸入的返回點,並且返回對應 try
的返回點。
因爲無法得知 輸入的參數數目,也無法指定特定項的參數,
所以擁有上限,不過一般情況應該不會有超過十個的不同錯誤需要捕捉,
若果真的超過了十個,可分拆為兩個 catch_end
。
/*throw*/
#define throw(ex_name, ...) \
\
setter_error_code(#ex_name); \
return __VA_ARGS__;
throw(拋出的錯誤名稱 [, 回傳值]);
於發生錯誤處使用,可指定拋出的錯誤名稱,
需指定拋出錯誤的函數返回的值,若函數的返回類型為
void
,第二項參數不需輸入。/*clear_throw*/
#define clear_throw() \
\
setter_error_code("");
若果拋出錯誤後不處理,又沒有調用
clear_throw
,有機會給
check
所意外捕捉。殘留直至捕捉處理。
/*check*/
#define check(...) \
\
if(strcmp(getter_error_code(), "")){ \
return __VA_ARGS__; \
}
若是,函數返回。(回到上一層)
基於拋出的錯誤是以殘留的方式存在,等價拋出錯誤。
void
,不需輸入。/*try$*/
#define try$(back_point, args) \
\
if(strcmp(getter_error_code(), "")){ \
setter_back_point(#back_point); \
if(strcmp(args, "")) \
setter_error_code(args); \
goto catch_start;\
} \
back_point:
/*try*/
#define try(back_point, ...) try$(back_point, "" #__VA_ARGS__)
try(返回點 [, 自行指定錯誤名稱])
必須指定返回點,返回點由
catch_end
檢測,並返回對應 try
的返回點。若第二項參數不輸入,默認使用
throw
所拋出的錯誤名稱。若輸入第二項參數,可自行指定錯誤名稱。
/*catch_start*/
#define catch_start(...) \
\
catch_start: \
if(!strcmp(getter_error_code(), "")) return __VA_ARGS__;
try
檢測到錯誤後都會到達 catch_start
點,一個參數,用於 正常(沒有發生錯誤)到達
catch_start
處時 指定返回的值,同樣,若函數的返回類型為
void
,不需輸入。return
。/*catch*/
#define catch(ex_name) \
\
if(!strcmp(getter_error_code(), #ex_name))
catch(錯誤名稱)
捕捉錯誤,發現對應的錯誤名稱時,運行對應區塊的代碼。
/*finally*/
#define finally()
因為在
catch_start
到 catch_end
的區間中,沒有被
catch
包括的都會被直接運行,所以
finally
是用於增加可讀性,給開發者看的。/*back*/
#define back(back_point) \
\
if(!strcmp(getter_back_point(), #back_point)){ \
goto back_point; \
}
/*get_11th_arg*/
#define get_11th_arg(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, arg11, ...) arg11
/*magic_bracket*/
#define magic_bracket(...) (__VA_ARGS__)
#define magic_left_bracket(...) (__VA_ARGS__
/*back2 - 10*/
#define back2(arg2, arg1) back(arg2) back(arg1) printf("[Error] 沒有透過 try 進入 catch / 找不到相應的返回點");
#define back3(arg3, ...) back(arg3) back2 magic_bracket(__VA_ARGS__)
#define back4(arg4, ...) back(arg4) back3 magic_bracket(__VA_ARGS__)
#define back5(arg5, ...) back(arg5) back4 magic_bracket(__VA_ARGS__)
#define back6(arg6, ...) back(arg6) back5 magic_bracket(__VA_ARGS__)
#define back7(arg7, ...) back(arg7) back6 magic_bracket(__VA_ARGS__)
#define back8(arg8, ...) back(arg8) back7 magic_bracket(__VA_ARGS__)
#define back9(arg9, ...) back(arg9) back8 magic_bracket(__VA_ARGS__)
#define back10(arg10, ...) back(arg10) back9 magic_bracket(__VA_ARGS__)
/*back_list 10-1*/
#define back_list back10, back9, back8, back7, back6, back5, back4, back3, back2, back
/*catch_end*/
#define catch_end(...) \
\
setter_error_code(""); \
get_11th_arg magic_left_bracket(__VA_ARGS__), back_list) (__VA_ARGS__)
catch_end(...)
擁有上限為十的可變參數,會清除/重置殘留的錯誤。參數為返回點,調用時會檢測所有輸入的返回點,並且返回對應
try
的返回點。所以擁有上限,不過一般情況應該不會有超過十個的不同錯誤需要捕捉,
若果真的超過了十個,可分拆為兩個
catch_end
。
0 Comments
發佈留言