gcc 如何在 constexpr 上下文中编译 C 函数?

How does gcc compile C functions in a constexpr context?

鉴于 ,考虑下面的程序。

#include <cmath>
#include <cstring>

int main()
{
    constexpr auto a = std::pow(2, 10);
    constexpr auto b = std::strlen("ABC");
}

正如预期的那样,MSVC++ 和 clang++ 无法编译它,因为 constexpr 变量是从未声明的函数初始化的 constexpr

然而,

g++ 编译它。 g++ 的版本似乎并不重要。

(See them all in compiler explorer)

g++ 是如何做到这一点的?这是正确的(允许的)编译器行为吗?

如前所述,C++ 标准库目前不支持 constexpr cmath 函数的计算。但是,这并不能阻止个别实现具有非标准代码。 GCC 有一个不一致的扩展 allows constexpr evaluation.

LWG 2013 的决议是不允许实现将非 constexpr 函数声明为 constexpr,因此 gcc 允许在编译时评估这些函数是不一致的时间.

也就是说,GCC 实际上并没有将需要的函数标记为 constexpr。相反,它所做的是尽早用 __builtin_pow__builtin_strlen 替换这些调用,它可以在编译时计算(std:: 版本调用 libc 版本,而后者不能)。这是一个编译器扩展。

如果你用-fno-builtin编译,它也无法同时编译std::powstd::strlen,但你可以通过显式写出[=19让clang和GCC都编译它=] 和 __builtin_strlen("ABC").