为什么不是abs constexpr?

Sho*_*hoe 15 c++ constexpr c++11

<cinttypes>,从C++ 11开始,有以下两个重载:

std::intmax_t abs( std::intmax_t n );
std::intmax_t imaxabs( std::intmax_t n );
Run Code Online (Sandbox Code Playgroud)

为什么不是这两个功能constexpr

lee*_*eek 7

P0533 中已经提出:

当且仅当以下情况下才<cmath>应声明 函数 in constexpr

  1. 当对有理数集起作用时,函数是封闭的(不包括被零除);
  2. 该函数不会修改任何具有外部可见性的参数;
  3. 该函数并不强烈依赖于舍入模式。

通过简要说明,abs满足所有三个标准;然而,功能,例如expsqrtcossin落入犯规第一标准的,因此被排除作为constexpr候选。最后,如上所述,nearbyint最终标准不合格。


Edw*_*ard 5

我不能给出为什么abs不能这么做的充分原因constexpr,显然也不可能gcc。当我gcc 4.9.2与此程序一起使用时:

#include <cstdlib>
#include <cinttypes>
#include <cassert>

constexpr intmax_t abs3 = std::abs(3);
constexpr intmax_t absneg3 = std::abs(-3);
int main()
{
    assert(abs3 == absneg3);
}
Run Code Online (Sandbox Code Playgroud)

它可以编译并完成,没有任何警告或错误。您可以在这里尝试。但是,clang++(版本3.5.0)会引发编译时错误:

abs.cpp:6:20:错误:constexpr变量'abs3'必须由常量表达式初始化。

我认为clang++实际上可以理解,因为在2011年标准的27.9.2节[c.files]中,它表示:

标头的内容与Standard C Library标头相同,但有以下更改:

—标头包含标头,而不是和

—当且仅当类型intmax_t指定扩展的整数类型(3.9.1)时,才添加以下函数签名:

intmax_t abs(intmax_t);

imaxdiv_t div(intmax_t,intmax_t);

它们应分别具有与函数签名intmax_t imaxabs(intmax_t)和imaxdiv_t imaxdiv(intmax_t,intmax_t)相同的语义。

在C ++标准的当前工作草案(如2014年发布的版本)中,它在第17.6.5.6节[constexpr.functions]中说:

该标准明确要求某些标准库函数为constexpr(7.1.5)。除非明确要求,否则实现不得将任何标准库函数签名声明为constexpr。

因此,目前的结果是,这些功能仍不constexpr符合标准(您知道),但gcc编译器已证明它们可以。