std::experimental::scope_success
| 定義於標頭檔 <experimental/scope> |
||
| template< class EF > class scope_success; |
(library fundamentals TS v3) | |
類別模板 scope_success 是一種通用的作用域防護(scope guard),旨在於作用域正常退出時呼叫其結束函式。
scope_success 不可 複製建構 (CopyConstructible)、複製賦值 (CopyAssignable) 或 移動賦值 (MoveAssignable)。然而,若 EF 滿足某些需求,它可能是 移動建構 (MoveConstructible) 的,這允許將 scope_success 封裝到另一個物件中。
scope_success 可以是「啟用」的(即在解構時呼叫其結束函式)或「停用」的(即在解構時不執行任何操作)。scope_success 在由結束函式建構後即為啟用狀態。
透過手動或自動(由移動建構子)在其上呼叫 release(),scope_success 可以變為停用狀態。使用另一個停用的 scope_success 進行初始化亦可獲得停用的 scope_success。一旦 scope_success 變為停用,它便無法再次變回啟用狀態。
scope_success 實際上持有一個 EF 和一個表示其是否啟用的 bool 旗標,以及一個用於偵測解構子是否在堆疊展開(stack unwinding)期間被呼叫的未捕捉異常計數器。
目錄 |
[edit] 模板參數
| EF | - | 所儲存的結束函式類型 |
| 類型要求 | ||
-EF 必須是下列其中之一:
| ||
| -以無參數形式呼叫 std::remove_reference_t<EF> 的左值必須是良構(well-formed)的。 | ||
[edit] 成員函式
建構一個新的 scope_success(公開成員函式) | |
若 scope_success 處於啟用狀態,則在作用域正常退出時呼叫結束函式,隨後解構 scope_success(公開成員函式) | |
| operator= [已刪除] |
scope_success 不可賦值(公開成員函式) |
修改器 | |
使 scope_success 變為停用狀態(公開成員函式) | |
[edit] 推導指引 (Deduction guides)
[edit] 附註
建構具有動態儲存週期的 scope_success 可能會導致非預期的行為。
由在不同執行緒中建立的另一個 scope_success 來建構 scope_success 也可能會導致非預期的行為,因為在解構期間可能會比較不同執行緒中獲得的未捕捉異常計數。
如果 scope_success 物件中儲存的 EF 參考了定義該物件的函式中的局部變數(例如,透過參考擷取該變數的 lambda),而該變數在該函式中被用作回傳運算元,那麼當 scope_success 的解構子執行並呼叫結束函式時,該變數可能已經被回傳了。這可能會導致令人驚訝的行為。
[edit] 範例
#include <iostream> #include <cstdlib> #include <string_view> #include <experimental/scope> void print_exit_status(std::string_view name, bool exit_status, bool did_throw) { std::cout << name << ":\n"; std::cout << " Throwed exception " << (did_throw ? "yes" : "no") << "\n"; std::cout << " Exit status " << (exit_status ? "finished" : "pending") << "\n\n"; } // Randomly throw an exception (50% chance) void maybe_throw() { if (std::rand() >= RAND_MAX / 2) throw std::exception{}; } int main() { bool exit_status{false}, did_throw{false}; // Manual handling at "end of scope" try { maybe_throw(); exit_status = true; } catch (...) { did_throw = true; } print_exit_status("Manual handling", exit_status, did_throw); // Using scope_exit: runs on scope exit (success or exception) exit_status = did_throw = false; try { auto guard = std::experimental::scope_exit{[&]{ exit_status = true; } }; maybe_throw(); } catch (...) { did_throw = true; } print_exit_status("scope_exit", exit_status, did_throw); // Using scope_fail: runs only if an exception occurs exit_status = did_throw = false; try { auto guard = std::experimental::scope_fail{[&]{ exit_status = true; } }; maybe_throw(); } catch (...) { did_throw = true; } print_exit_status("scope_fail", exit_status, did_throw); // Using scope_success: runs only if no exception occurs exit_status = did_throw = false; try { auto guard = std::experimental::scope_success{[&]{ exit_status = true; } }; maybe_throw(); } catch (...) { did_throw = true; } print_exit_status("scope_success", exit_status, did_throw); }
輸出
Manual handling: Throwed exception yes Exit status pending scope_exit: Throwed exception no Exit status finished scope_fail: Throwed exception yes Exit status finished scope_success: Throwed exception yes Exit status pending
[edit] 參見
| 封裝一個函式物件,並在退出作用域時呼叫它 (類別模板) | |
| 封裝一個函式物件,並在因異常退出作用域時呼叫它 (類別模板) | |
| (C++11) |
unique_ptr 的預設刪除器 (類別範本) |