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::pow
和std::strlen
,但你可以通过显式写出[=19让clang和GCC都编译它=] 和 __builtin_strlen("ABC")
.
鉴于
#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::pow
和std::strlen
,但你可以通过显式写出[=19让clang和GCC都编译它=] 和 __builtin_strlen("ABC")
.