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

时间:2017-06-09 18:39:06

标签: c++ c++11 g++ g++4.9

我的理解是函数std::isnan仅在C ++ 11之后可用。此外,g++使用-std=gnu++98,除非明确告知不要。{/ p>

那为什么要编译?

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

>> g++ test.cpp

是否有一个标志可以从<cmath>中取出该功能?

2 个答案:

答案 0 :(得分:5)

编译器开发人员很难完全删除应该只在下一版标准中提供的所有功能,特别是当相关库(C99)同时拥有它时。

实用程序(保护代码实际上遵循一个特定的标准)不足以让编译器编写者非常努力地使他们的编译器提供该服务。

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

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

它投入了一些努力而不是向后移植,但它并不是一个显示器。

答案 1 :(得分:2)

这是一个长期存在的问题,记录在案in the FAQ,但在某种程度上你不一定能理解。

  总是定义

4.3。 _XOPEN_SOURCE_GNU_SOURCE

     

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

     

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

     

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

     

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

     

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

     

已在邮件列表quite a bit上讨论过这个问题。

     

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

解释:

glibc提供标准C库。它支持多种模式。

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

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

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

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