C++ static_assert的用法(附带实例)
在 C++ 中,可以同时执行运行时和编译时断言检查,以确保代码中的特定条件为真。
运行时断言的缺点是,只有在程序运行时并且只有在控制流到达它们时,它们才会被验证。当条件依赖于运行时数据时,没有其他选择,然而,如果不是这样,编译时断言检查将是首选。
使用编译时断言,编译器能够在开发阶段的早期通知你某个特定条件未被满足。但是,只有当条件可以在编译时求值时,才能使用这些方法。在 C++11 中,编译时断言是通过 static_assert(静态断言检查) 执行的。
static_assert 最常见的用法是在模板元编程中使用,它们可以用于验证模板类型的先决条件是否满足(例如类型是否为 POD 类型、可复制构造类型、引用类型等)。另一个典型用例是确保类型(或对象)具有预期的大小。
当 static_assert 声明中的条件计算结果为 true 时,什么都不会发生;当条件的计算结果为 false 时,编译器生成一个包含指定 message(如果有的话)的错误。
使用 static_assert 声明来确保满足以下作用域中的条件:
1) 命名空间作用域,在本例中,我们验证 item 类的大小总是 16:
2) 类作用域,在本例中,我们验证 pod_wrapper 只能与 POD 类型一起使用:
3) 函数块作用域,在本例中,验证函数模板是否只有整型参数:
运行时断言的缺点是,只有在程序运行时并且只有在控制流到达它们时,它们才会被验证。当条件依赖于运行时数据时,没有其他选择,然而,如果不是这样,编译时断言检查将是首选。
使用编译时断言,编译器能够在开发阶段的早期通知你某个特定条件未被满足。但是,只有当条件可以在编译时求值时,才能使用这些方法。在 C++11 中,编译时断言是通过 static_assert(静态断言检查) 执行的。
static_assert 最常见的用法是在模板元编程中使用,它们可以用于验证模板类型的先决条件是否满足(例如类型是否为 POD 类型、可复制构造类型、引用类型等)。另一个典型用例是确保类型(或对象)具有预期的大小。
C++ static_assert的使用方式
static_assert 是一个声明,但它没有引入新名称。这些声明的形式如下:static_assert(condition, message);condition 必须在编译时转换为布尔值,且 message 必须是字符串字面量。在 C++17 中,message 是可选的。
当 static_assert 声明中的条件计算结果为 true 时,什么都不会发生;当条件的计算结果为 false 时,编译器生成一个包含指定 message(如果有的话)的错误。
使用 static_assert 声明来确保满足以下作用域中的条件:
1) 命名空间作用域,在本例中,我们验证 item 类的大小总是 16:
struct alignas(8) item { int id; bool active; double value; }; static_assert(sizeof(item) == 16, "size of item must be 16 bytes");
2) 类作用域,在本例中,我们验证 pod_wrapper 只能与 POD 类型一起使用:
template <typename T> class pod_wrapper { static_assert(std::is_standard_layout_v<T>, "POD type expected!"); T value; }; struct point { int x; int y; }; pod_wrapper<int> w1; // OK pod_wrapper<point> w2; // OK pod_wrapper<std::string> w3; // error: POD type expected
3) 函数块作用域,在本例中,验证函数模板是否只有整型参数:
template<typename T> auto mul(T const a, T const b) { static_assert(std::is_integral_v<T>, "Integral type expected"); return a * b; } auto v1 = mul(1, 2); // OK auto v2 = mul(12.0, 42.5); // error: Integral type expected