在 C++ 中编译时间浮点除以零
Compile time floating point division by zero in C++
众所周知,如果在 运行 时间内将一个浮点数除以零,那么结果将是无穷大或非数字(后一种情况,如果被除数也是零)。但是否允许在 C++ constexpr
表达式中除以零(在编译时),例如
#include <iostream>
int main() {
double x = 0.;
// run-time division: all compilers print "-nan"
std::cout << 0./x << std::endl;
// compile-time division, diverging results
constexpr double y = 0.;
std::cout << 0./y << std::endl;
}
在这个程序中,第一个打印的数字是从 运行 时间的除法中获得的,并且所有编译器在打印 -nan
上都非常一致。 (附带问题:为什么不 +nan
?)
但在第二种情况下,编译器出现分歧。 MSVC 只是停止编译并出现错误:
error C2124: divide or mod by zero
GCC 仍然打印 -nan
,而 Clang 更改了打印“positive”的符号 nan
,演示:https://gcc.godbolt.org/z/eP744er8n
语言标准是否允许编译器在编译时除法的所有三种行为:1) 拒绝程序,2) 产生与 运行-time 相同的除法结果,3) 产生不同的(符号位)结果?
除以零是未定义的行为。 (所以一切顺利)
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4713.pdf
第 8.5.5 节第 4 点
众所周知,如果在 运行 时间内将一个浮点数除以零,那么结果将是无穷大或非数字(后一种情况,如果被除数也是零)。但是否允许在 C++ constexpr
表达式中除以零(在编译时),例如
#include <iostream>
int main() {
double x = 0.;
// run-time division: all compilers print "-nan"
std::cout << 0./x << std::endl;
// compile-time division, diverging results
constexpr double y = 0.;
std::cout << 0./y << std::endl;
}
在这个程序中,第一个打印的数字是从 运行 时间的除法中获得的,并且所有编译器在打印 -nan
上都非常一致。 (附带问题:为什么不 +nan
?)
但在第二种情况下,编译器出现分歧。 MSVC 只是停止编译并出现错误:
error C2124: divide or mod by zero
GCC 仍然打印 -nan
,而 Clang 更改了打印“positive”的符号 nan
,演示:https://gcc.godbolt.org/z/eP744er8n
语言标准是否允许编译器在编译时除法的所有三种行为:1) 拒绝程序,2) 产生与 运行-time 相同的除法结果,3) 产生不同的(符号位)结果?
除以零是未定义的行为。 (所以一切顺利)
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4713.pdf 第 8.5.5 节第 4 点