【问题标题】:Infinity not constexpr无穷大不是 constexpr
【发布时间】:2017-09-22 20:17:44
【问题描述】:

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

#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 分配)。

AFAIK,因为 C++11、std::numeric_limits&lt;float&gt;::infinity()infinity()constexpr,所以我想知道 Clang 的问题出在哪里。


编辑 1:

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

还有必填的神螺栓链接:https://godbolt.org/g/Nd5yF9

编辑 2:

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

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

【问题讨论】:

标签: c++ c++17


【解决方案1】:

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

如果在计算表达式期间,结果未在数学上定义或不在其类型的可表示值范围内,则行为未定义。

这反过来意味着我们与[expr.const]/2.6发生冲突:

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

这意味着foo 的初始化器不是常量表达式,所以我们不能用它初始化constexpr 对象。


如果infinity() - epsilon()float 定义良好,这是一个clang 错误,代码格式正确。如果float 没有明确定义,这是一个 gcc 错误。

【讨论】:

  • 或者它可以明确定义为一个但不是另一个 :D Clang's constexpr evaluator 肯定将所有产生无穷大或 NaN 的表达式视为 UB。 C++ 标准对浮点几乎没有什么要说的。
猜你喜欢
  • 2022-08-12
  • 2019-03-19
  • 1970-01-01
  • 2013-11-29
  • 1970-01-01
  • 1970-01-01
  • 2011-08-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多