static_assert
declaration
(since C++11)
执行编译时断言检查。
目录 |
语法
static_assert(
布尔常量表达式
,
未求值字符串
)
|
(1) | ||||||||
static_assert(
布尔常量表达式
)
|
(2) | (C++17 起) | |||||||
static_assert(
布尔常量表达式
,
常量表达式
)
|
(3) | (C++26 起) | |||||||
声明一个静态断言。若断言失败,则程序非良构,并可能生成诊断错误信息。
说明
| bool-constexpr | - |
|
||||
| unevaluated-string | - | 一个将作为错误信息出现的 未求值字符串字面量 | ||||
| constant-expression | - |
满足以下所有条件的
常量表达式
msg
:
|
static_assert 声明可以出现在命名空间和作用域(作为块声明),也可以出现在类体内(作为成员声明)。
若 bool-constexpr 格式正确且求值为 true ,或在模板定义上下文中求值且模板未实例化,则此声明无实际作用。否则将产生编译时错误,且诊断信息中会包含用户提供的消息(若有)。
用户提供消息的文本按以下方式确定:
- 如果消息符合 unevaluated-string 的语法要求,则消息的文本即为该 unevaluated-string 的文本内容。
|
(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); // 自 C++17 起,消息字符串是可选的 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; // 在 CWG2518/P2593R1 之前的变通方案 template<class T> struct bad_type { static_assert(dependent_false<T>, "error on instantiation, workaround"); static_assert(false, "error on instantiation"); // 由于 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 // 还不是真正的 C++(std::format 应为 constexpr 才能工作): 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: 错误:静态断言失败:Swap requires copying 2: 错误:静态断言失败:Data structure requires default-constructible elements 3: 错误:静态断言失败: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] (页码: 10)
- C++20 标准 (ISO/IEC 14882:2020):
-
- 9.1 前导声明 [dcl.pre] (页: 6)
- C++17 标准 (ISO/IEC 14882:2017):
-
- 10 声明 [dcl.dcl] (页: 6)
- C++14 标准 (ISO/IEC 14882:2014):
-
- 7 声明 [dcl.dcl] (页: 4)
- C++11 标准 (ISO/IEC 14882:2011):
-
- 7 声明 [dcl.dcl] (页: 4)
参见
|
显示指定错误信息并使程序格式错误
(预处理指令) |
|
|
当用户指定条件不为
true
时终止程序。发行版本中可能被禁用
(函数宏) |
|
contract_assert
语句
(C++26)
|
在运行时验证内部条件 |
|
(C++11)
|
根据条件从重载决议中
移除
函数重载或模板特化
(类模板) |
| 类型特征 (C++11) | 定义基于模板的编译时接口以查询类型属性 |
|
C 文档
用于
静态断言
|
|