静态断言



类别 static_assert( … ) 宏 保证 何时 / 为何需要此断言 典型的失败场景
生命周期 / 析构 std::is_nothrow_destructible_v<T> 析构函数声明为 noexcept → 不会抛出异常。 对象可能在栈展开期间或工作线程上被销毁;抛出异常的析构函数会导致调用 std::terminate。 有人添加了 ~T() { if(err) throw; },或添加了析构函数可能抛出异常的成员。
  std::is_trivially_destructible_v<T> 编译器在析构函数中什么都不做(按位销毁)。 仅在极底层的 POD / 无锁代码中需要(例如存入 std::atomic<T>)。 添加了 std::vector、智能指针或用户自定义的析构函数。
移动 std::is_nothrow_move_constructible_v<T> 移动 T 不会抛出异常。 确保容器(std::vector、std::optional)维持强异常安全保证并避免拷贝。 从移动构造函数中移除了 noexcept,或添加了移动操作会抛出异常的成员。
  std::is_nothrow_move_assignable_v<T> 移动赋值为 noexcept。 原因同上;同时也能加速依赖快速 swap 的算法。 同上一列。
拷贝保护 !std::is_copy_constructible_v<T> 拷贝构造函数被删除。 大型 / 具有唯一性的对象绝不能被意外拷贝(例如转换表)。 某位贡献者移除了 = delete,意外启用了代价高昂的拷贝。
  !std::is_copy_assignable_v<T> 拷贝赋值运算符被删除。 同上。 同上。
拷贝成本 / POD 性质 std::is_trivially_copyable_v<T> 对象可以直接用 memcpy 移动(没有自定义的拷贝 / 移动 / 析构函数)。 高频按值传递的小型值类型、无锁队列中的数据。 添加了智能指针或用户自定义的拷贝 / 移动 / 析构函数。
可交换性 (C++17) std::is_nothrow_swappable_v<T> swap(a,b) 是 noexcept 且开销小。 让 STL 算法能够使用快速交换路径(例如在 std::sort、std::map::insert 内部)。 自定义的 swap() 失去了 noexcept,或移动操作开始抛出异常。


如何使用

#include <type_traits>
#include <utility>          // for std::is_nothrow_swappable_v

static_assert(std::is_nothrow_move_constructible_v<GTranslationTable>,
              "GTranslationTable move-ctor must be noexcept for vector reallocation!");

static_assert(!std::is_copy_constructible_v<GTranslationTable>,
              "Copying a translation table is disallowed — use move or shared_ptr.");


选择合适的断言

意图 建议使用的类型特征
对性能要求严格的值类型 std::is_trivially_copyable_v<T>
只进行移动操作的资源持有对象 删除拷贝操作 + 对两个无异常移动类型特征进行断言
跨线程共享的对象 至少断言 std::is_nothrow_destructible_v<T>
自定义 swap / 用于有序映射容器 添加 std::is_nothrow_swappable_v<T>