[英]Best practices for using `std::error_code`
我目前正在構建一個嵌入式系統並使用現代 C++ 編譯器。 雖然我在技術上可以在給定的資源(ARM7,超過 10M RAM)中進行異常處理,但我認為異常不是處理此類事情的正確工具,並且使用異常需要 RTTI,這反過來會導致代碼膨脹。
無論如何,為了保持 C++ 風格,我想使用std::error_code
(或類似的更多數據),因為我確實喜歡這個概念。
但是,對於如何實際使用它們似乎沒有任何共識。 我已經看到至少四種不同的方式在 function 調用之間傳遞它們,其中兩種具有多種語義。
通過指針作為參數傳遞
void somefunction(Args..., std::error_code* error);
這是我不經常看到的方式,也是我最不喜歡的方式。 它使返回類型完全可用,並且(通常但不總是)傳遞nullptr
導致正常的拋出行為。
通過引用作為參數傳遞
void somefunction(Args..., std::error_code& error);
這是我更喜歡的一個。 它使returnvalue
完全可用,並清楚地表明error_code
不是可選的。
按值返回
std::error_code somefunction(Ret& out <= if used, Args...);
我經常看到這個,但不是很喜歡它,因為它會耗盡你的返回值,而且我通常不喜歡“輸出參數”,除非沒有辦法繞過它們。
返回一個std::variant<Ret, std::error_code>
std::variant<Ret, std::error_code> somefunction(Args...);
這允許返回值,但使訪問值和錯誤更加困難。 此外,它使調用 function 的代碼更加冗長。
如果傳遞了error_code
,我已經看到了具有不同語義的方式1和2。
error_code
為“set”,則在開始時立即返回如果您想減少調用代碼中的錯誤檢查,最后一種方法非常好。 因為您可以只將一個error_code
傳遞給多個函數,而無需在兩者之間進行檢查,並且第一個錯誤之后的所有內容都不會執行,類似於異常的執行方式。
我個人確實更喜歡檢查和返回的方式2,但是我可能有偏見。
有一些推薦/普遍接受的方法嗎?
好的,這不是完整的答案,實際上也不是完美的主題,因為我不知道執行此操作的標准方法。 但是我曾經看到一個漂亮的小技巧,可以讓錯誤代碼更難被誤用。 考慮以下代碼:
struct MyEC { MyEC() {} MyEC(MyEC && other) : parent(&other) { // Maybe log and or abort if other is not checked other.checked = false; } // Delete other constructors and assignment operators ~MyEC() { if(!checked && parent == nullptr) { // log and or abort } } [[nodiscard]] std::error_code check() { checked = true; return ec; } void set(std::error_code err) { if(parent == nullptr) ec = err; else parent->set(err); } private: MyEC* parent = nullptr; checked = true; std::error_code ec {}; }; int foo(MyEC&& err) { err.set(/* some error */); return 5; } int foo1(MyEC&&) { return 4; } void bar() { MyEC err; foo(std::move(err)); // err has the error code and if its not checked, we will know foo1(std::move(err)); // even though no error occurs, we will abort if err is not checked. }
當錯誤代碼未設置但也未檢查時,它甚至會中止,這非常好。 移動后有很多用處,有點奇怪,不過這里沒問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.