在<cinttypes>
中,自C ++ 11以来,有the following two次重载:
std::intmax_t abs( std::intmax_t n );
std::intmax_t imaxabs( std::intmax_t n );
为什么这两个函数不是constexpr
?
答案 0 :(得分:4)
我无法说明为什么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);
}
时:
clang++
它编译并运行完成,没有任何警告或错误。你可以try it here。但是,clang++
(版本3.5.0)会抛出编译时错误:
abs.cpp:6:20:错误:constexpr变量'abs3'必须用常量表达式初始化。
我认为constexpr
实际上是正确的,因为在2011年标准的第27.9.2节[c.files]中,它说:
标题的内容与标准C库标题相同,但有以下更改:
- 标题包含标题而不是
- 当且仅当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,除非是它 明确要求。
因此,目前的结果是,根据标准(您知道),这些函数仍然不是gcc
,但它们可能是{{1}}编译器所证明的。
答案 1 :(得分:2)
已在P0533中提出:
必须声明
<cmath>
中的一个函数constexpr
仅当且仅当:
- 当对有理数集采取行动时, 该函数已关闭(不包括零除);
- 该函数不会修改其任何参数 具有外部可见性;
- 该功能并不强烈依赖于 舍入模式。
通过简要说明,
abs
满足所有三个条件;但是,诸如exp
,sqrt
,cos
,sin
之类的功能不符合第一个条件,因此被排除为constexpr
个候选者。最后,如上所述,nearbyint
不符合最终标准。
答案 2 :(得分:1)
简单的解释可能是没有人经历作为标准库一部分列出的每个函数,并更新了条目以使其成为constexpr
。
更新标准是一个涉及人力建议变更并使这些建议得到审核和接受的过程。这意味着,当添加新功能时 - constexpr
是一项新功能 - 并非所有其他功能都会自动更新以使用该功能。这个特殊情况可能会在标准的未来演变中得到更新 - 如果有些人采取 - 经常是吃力不讨好 - 提出一系列变更的任务,其他一些人承担审查它的任务,并说服具有投票权的人在委员会接受它。