2017-04-17 65 views
0

要防呆,它需要:哪個C++功能可以確保從選項<T>中提取T&T?

  • 清晰的語法
  • 可能使用auto
  • 原子的使用,以防止意外的失誤像if (!opt) { opt->call(); }
  • 沒有運行時斷言(編輯 :和例外)
  • 無編譯器警告
  • (可選)無靜態檢查器警告GS

到目前爲止,我已經試過這4個選項(假設具有可變optional<T> opt;):

選項0標準用法

if (opt) { 
    opt->call(); 
} 
  • +清潔代碼
  • +自然控制流量,有else聲明
  • -不是原子
  • -operator->在可空類型被暴露,所以很容易調用opt->call()if檢查

選項1.創建一個智能指針almost_present<T>_DEBUG-只有字段mutable boolean checkedPresent設置爲true當用戶確實operator bool

if (almost_present<T> nonull = opt.if_present()) { 
    // `operator->()` and `operator T&()` assert if called without doing `if (nonull)` 
    nonull->call(); 
    T& x = nonull; 
} 
  • +自然控制流程,具有else聲明
  • +將斷言,如果用戶沒有引用之前檢查值,即使它是目前
  • -運行時檢查
  • -almost_present<T>::operator bool() const必須修改checkedPresent字段
  • -可能會意外地在else分支使用nonull,但這是次要的

選項2。範圍爲基礎的循環招從http://loungecpp.net/cpp/abusing-range-for/optional<T>optional<T>::if_present()實現方法begin()end()看起來像0或1項

for (auto& nonull : opt.if_present()) { 
    nonull.call(); 
} 
  • +集合簡潔的語法
  • -無條件return在任何迴路內產生warning C4702: unrechable code(VC2017)
  • -沒有else聲明,必須單獨調用if (!opt),這不是原子
  • -看起來像一個循環,可能會誤解,如果T是一家集

選項3 Lambda表達式

opt.if_present([](auto& nonull) { nonull.call(); }); 
auto result = opt.map(
     [](auto& nonull) { return nonull.call(); }, 
     []() { return what_if_null(); } 
    ); 
  • +它的工作原理
  • -沒有一個清晰的語法 - 難以閱讀和調試

現在,我使用的組合 「for」 循環和 「lambda表達式」

+0

幾乎目前看起來對我來說是可選的。 – Yakk

+0

除了娛樂之外,我不會使用.2和.3。這種代碼有效地混淆了。 – Pavel

+0

@Yakk,'almost_present'如果您忘記了'if',則會預防性地斷言,所以用1個測試覆蓋此代碼就足夠了。而'std :: optional '只會在你傳遞一個空值時失敗,這可能非常少見。 –

回答

0
auto v = opt.value(); 

拋出一個bad_optional_access如果opt包含沒有價值。

+0

嗯,那正是我想要避免的 - 運行時斷言並拋出 –

+0

@MykolaBogdiuk你沒有提到你想避免異常。 –

+0

正式的是,但我不會使用'可選的',如果我明確地知道它不是空的話。將編輯該問題。 –

相關問題