当测试条件包含用 const 定义的常量时,static_assert 失败?

问题描述 投票:0回答:2

我正在阅读 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");
 } 
c++11 error-handling
2个回答
0
投票

编译器在编译时并不知道

speed
的值。它无法在编译时评估
speed < C
,这是有道理的。因此,在处理该行时预计会出现编译时错误

static_assert(speed<C,"can't go that fast");

该语言不保证在编译时计算浮点表达式。有些编译器可能支持它,但这并不可靠。

尽管浮点变量的值对于人类读者来说是“常量”,但它们不一定在编译时进行评估。您提供的链接中来自编译器的错误消息清楚地表明了这一点。

static_assert expression is not an integral constant expression

您必须找到一种使用积分表达式进行比较的方法。然而,这似乎是一个有争议的问题。我怀疑,您真正想做的是确保

speed
在一定范围内。这仅作为运行时检查才有意义。


0
投票

因为书中的代码片段是一个错误并且根本不正确,所以后来在《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 // ...
    }

 
© www.soinside.com 2019 - 2024. All rights reserved.