【问题标题】:Why isn't abs constexpr?为什么不是 abs constexpr?
【发布时间】:2026-01-29 17:45:02
【问题描述】:

<cinttypes>中,从C++11开始,就有the following two重载:

std::intmax_t abs( std::intmax_t n );
std::intmax_t imaxabs( std::intmax_t n );

为什么不是constexpr这两个函数?

【问题讨论】:

  • @BasileStarynkevitch:您能解释一下这些兼容性原因之一吗?
  • @BasileStarynkevitch 我不买那个。给定一个兼容的编译器,一段 constexpr 代码将与它使用的一样工作,即当传入非 constexpr 值时,它将返回一个非 constexpr。如果最好不使这些函数为 constexpr (或与 constexpr 重载)兼容,那么最好不包括矢量的移动指导。由于它使用命名空间(所以不是 C)并且是仅在 C++11 中提供的标头,我希望看到 constexpr overlaods。
  • abs 是一个 C99 函数。而C99不知道constexpr
  • 很多 函数可能是 constexpr 而不是 (还)。随着标准的每次修订,更多的函数将慢慢变成 constexpr。随意参与该过程(isocpp.org 上的说明)。
  • abs 不是constexpr,因为标准是这样决定的。我认为这是问为什么的错误地方。我可以说的是,如果您真的需要constexpr abs,请编写您自己的。你不会出错的。

标签: c++ c++11 constexpr


【解决方案1】:

我不能很好地解释为什么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);
}

它编译并运行完成,没有警告或错误。你可以try it here。但是,clang++(版本 3.5.0)会引发编译时错误:

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

我认为clang++ 实际上在这里得到了它,因为在 2011 标准的第 27.9.2 [c.files] 节中,它说:

header 内容与标准 C 库 header 相同,有以下变化:

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

——当且仅当类型 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++ 标准的 current working draft 中,与 2014 年发布的版本一样,它在第 17.6.5.6 节 [constexpr.functions] 中说:

此标准明确要求某些标准库函数为 constexpr (7.1.5)。实现不应将任何标准库函数签名声明为 constexpr,除非它在 是明确要求的。

因此,目前的结果是,这些函数仍然不是 constexpr 根据标准(您知道),但它们可能是,正如 gcc 编译器所证明的那样。

【讨论】:

【解决方案2】:

已在P0533提出:

应声明&lt;cmath&gt; 中的函数 constexpr 当且仅当:

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

通过简要说明,abs 满足所有三个条件;但是,expsqrtcossin 等函数违反了第一个标准,因此被排除为 constexpr 候选对象。最后,如上所述,nearbyint 不符合最终标准。

【讨论】:

    【解决方案3】:

    简单的解释可能是没有人检查作为标准库的一部分列出的每个函数,并将条目更新为constexpr

    更新标准是一个涉及人工提出更改建议并让这些建议得到审核和接受的过程。这意味着,当添加新功能时 - 并且 constexpr 是新功能 - 并非所有其他内容都会自动更新以使用该功能。这种特殊情况很可能会在标准的未来发展中得到更新——如果一些人承担——通常是吃力不讨好的——提出一组更改的任务,其他人承担审查它的任务,并说服那些有投票权的人在委员会接受它。

    【讨论】: