static_assert的条件必须是编译期可求值的常量表达式,如字面量、sizeof、模板参数、constexpr函数结果等;不可依赖运行时变量、非constexpr函数调用或非常量对象成员。

static_assert 的条件必须是常量表达式
它不能依赖运行时变量、函数调用(除非是 constexpr 函数)、对象成员访问(非 static const)或任何无法在编译期求值的东西。编译器看到 static_assert 就会立刻尝试计算其第一个参数,失败就报错。
常见错误现象:error: non-constant condition for static assertion 或类似提示,往往是因为你用了普通函数返回值、this、局部变量、未初始化的 constexpr 变量等。
- ✅ 正确:字面量、
sizeof、alignof、模板参数、constexpr变量/函数结果 - ❌ 错误:
static_assert(func(), "...")(func不是 constexpr)、static_assert(x > 0, "...")(x是普通int) - ⚠️ 注意:C++17 起支持带消息字符串的重载,但条件本身仍须是常量表达式;C++20 起允许更宽松的 constexpr 上下文,但基础限制没变
怎么写带模板参数的条件
这是 static_assert 最典型的使用场景——约束模板实参。条件里直接用模板形参名即可,只要它能参与常量表达式计算。
template<typename T>
struct container {
static_assert(sizeof(T) > 0, "T must be a complete type");
static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable");
};
说明:std::is_trivially_copyable_v<T> 是 C++17 引入的变量模板,本质是 constexpr 布尔值,完全合法;而 sizeof(T) 在模板实例化时已知,也是常量表达式。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
立即学习“C++免费学习笔记(深入)”;
- 别写
static_assert(std::is_trivially_copyable<T>::value, ...)—— 多余且易读性差,用_v后缀更直接 - 如果条件涉及多个逻辑,用括号明确优先级:
static_assert((std::is_integral_v<T> || std::is_enum_v<T>) && sizeof(T) <= 8, ...) - 避免在类模板外提前实例化导致断言过早触发,比如把
static_assert放在偏特化内部而非主模板中
为什么空字符串消息在某些编译器会警告
旧标准(C++11/C++14)只允许 static_assert(Cond) 无消息形式;C++17 起才支持 static_assert(Cond, Msg)。如果你写了 static_assert(true, ""),部分编译器(如较老版本 GCC)可能报 warning: empty string in static_assert,不是错误,但说明你可能误用了空消息。
- ✅ 推荐写法:
static_assert(sizeof(int) == 4, "int must be 4 bytes on this platform") - ❌ 不要写:
static_assert(condition, "")—— 没意义,还可能触发警告 - ⚠️ 消息字符串必须是字符串字面量(
"..."),不能是const char*变量或拼接结果
和 assert 宏混用时容易踩的坑
static_assert 和 assert 完全不同层:前者纯编译期检查,后者是运行时宏,依赖 NDEBUG。很多人想“既编译期又运行时检查”,结果写出两套重复逻辑,或者误以为 static_assert 能捕获运行时值。
- 别用
static_assert替代边界检查:比如数组索引i < size—— 这必须用assert(i < size)或其它运行时手段 - 别在头文件里无条件写
static_assert(sizeof(void*) == 8),这会让 32 位平台编译直接失败;应结合#ifdef或用更柔性的条件,比如static_assert(sizeof(void*) >= 4) - 模板中混合使用时,注意 SFINAE:
static_assert触发失败会导致硬错误(hard error),而不是让重载被丢弃;要用std::enable_if_t或 C++20requires做软约束

















