名稱空間
變體
操作

static_assert 宣告 (C++11 起)

來自 cppreference.com
< cpp‎ | 語言
 
 
C++ 語言
 
 

執行編譯時斷言檢查。

目錄

[編輯] 語法

static_assert( 布林常量表達式 , 未求值字串 ) (1)
static_assert( 布林常量表達式 ) (2) (C++17 起)
static_assert( 布林常量表達式 , 常量表達式 ) (3) (C++26 起)

宣告一個靜態斷言。如果斷言失敗,程式格式不正確,並且可能會生成診斷錯誤訊息。

1) 帶有固定錯誤訊息的靜態斷言。
2) 沒有錯誤訊息的靜態斷言。
3) 帶有使用者生成錯誤訊息的靜態斷言。
只有當語法 (1) 不匹配時,才能匹配此語法。

[編輯] 解釋

布林常量表達式 -

一個上下文轉換的 bool 型別常量表達式。不允許內建轉換,除了非窄化 整型轉換bool

(直至 C++23)

一個上下文轉換為 bool 的表示式,其中轉換是一個常量表達式

(C++23 起)
未求值字串 - 一個未求值的字串字面量,它將作為錯誤訊息出現
常量表達式 - 一個常量表達式 msg 滿足以下所有條件
  • msg.size() 隱式轉換為 std::size_t
  • msg.data() 隱式轉換為 const char*

一個 static_assert 宣告可以出現在名稱空間和塊作用域(作為塊宣告)以及類體內(作為成員宣告)。

如果 布林常量表達式 格式正確且求值為 true,或者在模板定義的上下文中求值且模板未例項化,則此宣告無效。否則,將發出編譯時錯誤,並且診斷訊息中將包含使用者提供的訊息(如果有)。

使用者提供訊息的文字確定如下

  • 如果訊息匹配 未求值字串 的語法要求,則訊息的文字是 未求值字串 的文字。
  • 否則,給定以下值
訊息的文字由 len程式碼單元序列構成,從 ptr 開始,使用普通字面量編碼。對於 [0len) 中的每個整數 iptr[i] 必須是整型常量表達式
(C++26 起)

[編輯] 注意

標準不要求編譯器列印錯誤訊息的逐字文字,儘管編譯器通常會盡可能這樣做。

由於錯誤訊息必須是字串字面量,它不能包含動態資訊,甚至不能包含本身不是字串字面量的常量表達式。特別是,它不能包含模板型別引數名稱

(直到 C++26)
功能測試宏 標準 特性
__cpp_static_assert 200410L (C++11) static_assert (語法 (1))
201411L (C++17) 單引數 static_assert (語法 (2))
202306L (C++26) 使用者生成錯誤訊息 (語法 (3))

[編輯] 關鍵詞

static_assert

[編輯] 示例

#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 文件 用於 靜態斷言