为什么 g++ 4.9.0 默认有 std::isnan?



我的理解是,函数std::isnan仅在C++11开始可用。此外,除非特别说明不要使用-std=gnu++98,否则g++使用。

那么为什么要编译呢?

>> cat test.cpp
#include <cmath>
int main(int argc, char** argv)
{
return std::isnan(0);
}
>> g++ test.cpp

是否有一个标志可以将该功能从<cmath>中删除?

编译器开发人员懒得完全删除仅在下一版本的标准中可用的每个功能,尤其是当相关库(C99)同时拥有它时。

实用程序(验证代码是否实际遵守特定标准)不足以让编译器编写者非常努力地使其编译器提供该服务。

相反,通常发生的事情是在特定标准标志下实现新功能。 有时它们会被意外地向后移植。 当标准最终确定时,部分实现会存在一段时间,直到它变得足够好。

然后开始下一个版本的标准工作。 下一个版本标志为您提供了一个不太稳定的开发环境,因为新功能被试用、丢弃和更改。

它为不向后移植的东西付出了一些努力,但它并不是一个阻碍。

这是一个长期存在的问题,记录在常见问题解答中,但以一种您不一定能够理解的方式。

4.3._XOPEN_SOURCE_GNU_SOURCE总是被定义?

在 Solaris 上,g++(但不是gcc)总是定义预处理器宏_XOPEN_SOURCE在 GNU/Linux 上,同样的情况也发生在_GNU_SOURCE上。(这不是一个详尽的列表;其他宏和其他平台也会受到影响。

这些宏通常用于 C 库标头中,保护新版本的函数与其旧版本。C++98 标准库包括 C 标准库,但它需要 C90 版本,出于向后兼容性的原因,C90 版本通常不是许多供应商的默认版本。

更重要的是,C++标准要求的行为仅在定义某些符号后在某些平台上可用。通常问题涉及与 I/O 相关的类型定义。为了确保正确性,编译器只需预定义这些符号。

请注意,仅在构建库时(在安装期间)#define它们是不够的。由于我们没有"export"关键字,因此大部分库都以标头形式存在,这意味着在解析和编译程序时也必须定义符号。

要查看定义了哪些符号,请在目标的 gcc config 标头中查找CPLUSPLUS_CPP_SPEC(并尝试更改它们以查看构建复杂代码时会发生什么)。您还可以运行g++ -E -dM - [原文如此] 来显示任何特定安装的预定义宏列表。

这在邮件列表中已经讨论了很多。

这种方法有点像疣。我们希望找到一个更清洁的解决方案,但还没有人贡献时间。

解释一下:

glibc 是提供标准 C 库的东西。它支持多种模式。

它支持各种严格的C模式和严格的POSIX模式。在这些模式下,当仅包含标准标头时,只有标准函数可用。在C90模式下,这不包括isnan

它支持各种扩展模式。在这些模式下,还可以使用非标准功能。在 C90 + 扩展模式下,这包括isnan._GNU_SOURCE预处理器宏是启用所有扩展的宏。

libstdc++是提供标准C++库的东西。它对 glibc 的要求比严格的 C90 模式提供的要多。因此,只有两个选择:libstdc++ 不提供它无法提供的标准C++功能,或者 libstdc++ 即使在严格的 ANSI 模式下也强制启用 glibc 的扩展。两者都意味着不符合C++标准,但前者限制了功能,而后者提供了功能。后者被视为较小的邪恶。

解决此问题的唯一合理方法是让 glibc 提供一些非标准的方式来访问其扩展,即使在严格的 ANSI 模式下也是如此。目前还没有这样的方法,在创建这种方式之前,即使在标准C++编译模式下,非标准名称也将可用。

最新更新