static_assert
宣告 (C++11 起)
來自 cppreference.com
執行編譯時斷言檢查。
目錄 |
[編輯] 語法
static_assert( 布林常量表達式 , 未求值字串 ) |
(1) | ||||||||
static_assert( 布林常量表達式 ) |
(2) | (C++17 起) | |||||||
static_assert( 布林常量表達式 , 常量表達式 ) |
(3) | (C++26 起) | |||||||
宣告一個靜態斷言。如果斷言失敗,程式格式不正確,並且可能會生成診斷錯誤訊息。
1) 帶有固定錯誤訊息的靜態斷言。
2) 沒有錯誤訊息的靜態斷言。
3) 帶有使用者生成錯誤訊息的靜態斷言。
只有當語法 (1) 不匹配時,才能匹配此語法。
[編輯] 解釋
布林常量表達式 | - |
| ||||
未求值字串 | - | 一個未求值的字串字面量,它將作為錯誤訊息出現 | ||||
常量表達式 | - | 一個常量表達式 msg 滿足以下所有條件
|
一個 static_assert 宣告可以出現在名稱空間和塊作用域(作為塊宣告)以及類體內(作為成員宣告)。
如果 布林常量表達式 格式正確且求值為 true,或者在模板定義的上下文中求值且模板未例項化,則此宣告無效。否則,將發出編譯時錯誤,並且診斷訊息中將包含使用者提供的訊息(如果有)。
使用者提供訊息的文字確定如下
- 如果訊息匹配 未求值字串 的語法要求,則訊息的文字是 未求值字串 的文字。
|
(C++26 起) |
[編輯] 注意
標準不要求編譯器列印錯誤訊息的逐字文字,儘管編譯器通常會盡可能這樣做。
由於錯誤訊息必須是字串字面量,它不能包含動態資訊,甚至不能包含本身不是字串字面量的常量表達式。特別是,它不能包含模板型別引數的名稱。 |
(直到 C++26) |
功能測試宏 | 值 | 標準 | 特性 |
---|---|---|---|
__cpp_static_assert |
200410L |
(C++11) | static_assert (語法 (1)) |
201411L |
(C++17) | 單引數 static_assert (語法 (2)) | |
202306L |
(C++26) | 使用者生成錯誤訊息 (語法 (3)) |
[編輯] 關鍵詞
[編輯] 示例
執行此程式碼
#include <format> #include <type_traits> static_assert(03301 == 1729); // since C++17 the message string is optional template<class T> void swap(T& a, T& b) noexcept { static_assert(std::is_copy_constructible_v<T>, "Swap requires copying"); static_assert(std::is_nothrow_copy_constructible_v<T> && std::is_nothrow_copy_assignable_v<T>, "Swap requires nothrow copy/assign"); auto c = b; b = a; a = c; } template<class T> struct data_structure { static_assert(std::is_default_constructible_v<T>, "Data structure requires default-constructible elements"); }; template<class> constexpr bool dependent_false = false; // workaround before CWG2518/P2593R1 template<class T> struct bad_type { static_assert(dependent_false<T>, "error on instantiation, workaround"); static_assert(false, "error on instantiation"); // OK because of CWG2518/P2593R1 }; struct no_copy { no_copy(const no_copy&) = delete; no_copy() = default; }; struct no_default { no_default() = delete; }; #if __cpp_static_assert >= 202306L // Not real C++ yet (std::format should be constexpr to work): static_assert(sizeof(int) == 4, std::format("Expected 4, got {}", sizeof(int))); #endif int main() { int a, b; swap(a, b); no_copy nc_a, nc_b; swap(nc_a, nc_b); // 1 [[maybe_unused]] data_structure<int> ds_ok; [[maybe_unused]] data_structure<no_default> ds_error; // 2 }
可能的輸出
1: error: static assertion failed: Swap requires copying 2: error: static assertion failed: Data structure requires default-constructible elements 3: error: static assertion failed: Expected 4, got 2
[編輯] 缺陷報告
下列更改行為的缺陷報告追溯地應用於以前出版的 C++ 標準。
缺陷報告 | 應用於 | 釋出時的行為 | 正確的行為 |
---|---|---|---|
CWG 2039 | C++11 | 只有轉換前的表示式才要求是常量 | 轉換也必須是 在常量表達式中有效 |
CWG 2518 (P2593R1) |
C++11 | 未例項化的 static_assert(false, ""); 格式不正確 | 使其格式正確 |
[編輯] 參考文獻
- C++23 標準 (ISO/IEC 14882:2024)
- 9.1 導言 [dcl.pre] (p: 10)
- C++20 標準 (ISO/IEC 14882:2020)
- 9.1 導言 [dcl.pre] (p: 6)
- C++17 標準 (ISO/IEC 14882:2017)
- 10 宣告 [dcl.dcl] (p: 6)
- C++14 標準 (ISO/IEC 14882:2014)
- 7 宣告 [dcl.dcl] (p: 4)
- C++11 標準 (ISO/IEC 14882:2011)
- 7 宣告 [dcl.dcl] (p: 4)
[編輯] 另見
顯示給定錯誤訊息並使程式格式不正確 (預處理指令) | |
如果使用者指定條件不為 true,則中止程式。在釋出版本中可能會停用。 (函式宏) | |
contract_assert 語句 (C++26) |
在執行期間驗證內部條件 |
(C++11) |
有條件地從過載解析中移除函式過載或模板特化 (類模板) |
型別特性 (C++11) | 定義編譯時基於模板的介面以查詢型別的屬性 |
C 文件 用於 靜態斷言
|