无限不是constexpr [英] Infinity not constexpr

查看:69
本文介绍了无限不是constexpr的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想测试无限附近的浮点数的行为。为此,我天真地写了以下代码:

I wanted to test the behavior of floats near infinity. For that I naively wrote the following code:

#include <limits>
#include <iostream>

int main() {
    constexpr float foo = std::numeric_limits<float>::infinity() - std::numeric_limits<float>::epsilon();
    std::cout << foo << std::endl;
    return foo;
}

对我来说有趣的部分是,它在GCC 7.2中可以很好地编译,但在Clang 5(抱怨 foo 的非constexpr赋值)。

The interesting part to me was that this compiles fine in GCC 7.2 but fails on Clang 5 (complaining about non-constexpr assign of foo).

AFAIK,因为C ++ 11, std :: numeric_limits< float> :: infinity() infinity() constexpr ,所以我想知道Clang的问题在哪里。

AFAIK, since C++11, std::numeric_limits<float>::infinity() and infinity() are constexpr, so I am wondering where the problem lies for Clang.

编辑1:

删除了不必要的 static_assert
感谢您指向被0除。IMO引用的标准文本在此处不适用!?

Removed unnecessary static_assert. Thanks for pointing to division by 0. IMO the quoted standards text there does not apply here!?

还有强制性的godbolt链接: https://godbolt.org/g/Nd5yF9

And the obligatory godbolt link: https://godbolt.org/g/Nd5yF9

编辑2:

请注意,相同的行为适用于:

Note that the same behavior applies to:

constexpr float foo = std::numeric_limits<float>::infinity() - 100.0f;


推荐答案

我对浮点规则不是特别熟悉,但我怀疑我们可能与 [expr] / 4

I'm not particularly familiar with floating point rules, but I'd suspect that we might be running afoul of [expr]/4:


如果在对表达式求值时,其结果在数学上未定义或不在其可表示值的范围内类型,行为是不确定的。

If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined.

反过来,这意味着我们违反了 [expr.const] /2.6

Which, in turn, means we run afoul of [expr.const]/2.6:


表达式e是核心常量表达式,除非按照抽象机的规则对e求值将对以下表达式之一求值:[...]具有[[]中指定的未定义行为的操作本文档的[cpp]简介

An expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine, would evaluate one of the following expressions: [...] an operation that would have undefined behavior as specified in [intro] through [cpp] of this document

foo 不是常量表达式,因此我们无法使用它初始化 constexpr 对象。

That means the initializer for foo isn't a constant expression, so we can't initialize a constexpr object with it.

如果 infinity()-epsilon()很好-为 float 定义的,这是一个clang错误,代码格式正确。如果对 float 的定义不明确,则说明这是gcc错误。

If infinity() - epsilon() is well-defined for float, this is a clang bug, the code is well-formed. If it's not well-defined for float, this is a gcc bug.

这篇关于无限不是constexpr的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆