我正在阅读 Bjarne Stroustrup 的书《C++ 编程语言》,我发现了一个解释的示例
static_assert
。我的理解是 static_assert
只适用于可以用常量表达式表达的东西。换句话说,它不能包含要在运行时计算的表达式。
书中使用了以下示例(我对代码做了一些更改。但我认为这不会改变书中给出的原始示例代码生成的任何内容。)
#include <iostream>
using namespace std;
void f (double speed)
{
constexpr double C = 299792.468;
const double local_max = 160.0/(60*60);
static_assert(local_max<C,"can't go that fast");
}
int main()
{
f(3.25);
cout << "Reached here!";
return 0;
}
上面给出了编译错误。这是使用 ideone 编译的:http://ideone.com/C97oF5
书中示例的确切代码:
constexpr double C = 299792.458;
void f(double speed)
{
const double local_max = 160.0/(60∗60);
static_assert(speed<C,"can't go that fast"); // yes this is error
static_assert(local_max<C,"can't go that fast");
}
编译器在编译时并不知道
speed
的值。它无法在编译时评估 speed < C
,这是有道理的。因此,在处理该行时预计会出现编译时错误
static_assert(speed<C,"can't go that fast");
该语言不保证在编译时计算浮点表达式。有些编译器可能支持它,但这并不可靠。
尽管浮点变量的值对于人类读者来说是“常量”,但它们不一定在编译时进行评估。您提供的链接中来自编译器的错误消息清楚地表明了这一点。
static_assert expression is not an integral constant expression
您必须找到一种使用积分表达式进行比较的方法。然而,这似乎是一个有争议的问题。我怀疑,您真正想做的是确保
speed
在一定范围内。这仅作为运行时检查才有意义。
因为书中的代码片段是一个错误并且根本不正确,所以后来在《C++之旅》第二版中同一作者在另一本书中更正了它。
错误是这样的
const local_max = 160.0/(60*60);
不能用于
static_assert(local_max<C,"can't go that fast");
因为
const
变量是在运行时评估的,而 static_assert(...)
需要编译时变量。然而, constexpr
是在编译时评估的,因此可以在 static_assert(...)
函数中使用。
因此,定义 local_max 的正确方法是使用 constexpr
关键字,而不是 const
constexpr local_max = 160.0/(60*60);
“C++ 编程语言”一书中找到的旧(不正确)片段
constexpr double C = 299792.458; // km/s
void f(double speed) {
const double local_max = 160.0/(60*60); // 160 km/h == 160.0/(60*60) km/s
static_assert(speed<C,"can't go that fast"); // error: speed must be a constant
static_assert(local_max<C,"can't go that fast"); // OK // ...
}
更新了“C++ 之旅(第二版)”中的(正确)片段
constexpr double C = 299792.458; // km/s
void f(double speed) {
constexpr double local_max = 160.0/(60∗60); // 160 km/h == 160.0/(60*60) km/s
static_assert(speed<C,"can't go that fast"); // error: speed must be a constant
static_assert(local_max<C,"can't go that fast"); // OK // ...
}