为什么 g++ 4.9.0 默认有 std::isnan?
Why does g++ 4.9.0 have std::isnan by default?
我的理解是函数 std::isnan
只能从 C++11 开始使用。此外,g++
使用 -std=gnu++98
除非明确告知不要这样做。
那么为什么要编译?
>> cat test.cpp
#include <cmath>
int main(int argc, char** argv)
{
return std::isnan(0);
}
>> g++ test.cpp
是否有将函数从 <cmath>
中取出的标志?
编译器开发人员懒于完全删除应该只在下一版本标准中可用的每个功能,尤其是当相关库 (C99) 同时具有它时。
实用程序(验证您的代码实际上是否遵守特定标准)不足以让编译器编写者非常努力地让他们的编译器提供该服务。
相反,通常发生的情况是新功能是在特定标准标志下实现的。有时他们会被意外地向后移植。当标准最终确定时,部分实现会存在一段时间,直到它变得足够好。
然后开始制定下一版本的标准。下一个版本标志为您提供了一个不太稳定的开发环境,因为新功能被尝试、丢弃和更改。
它在不向后移植方面付出了一些努力,但它并不是一个引人注目的东西。
这是一个 long-standing 问题,已记录在案 in the FAQ,但您不一定能够理解。
4.3. _XOPEN_SOURCE
and _GNU_SOURCE
are always defined?
On Solaris, g++ (but not gcc) always defines the preprocessor macro _XOPEN_SOURCE
. On GNU/Linux, the same happens with _GNU_SOURCE
. (This is not an exhaustive list; other macros and other platforms are also affected.)
These macros are typically used in C library headers, guarding new versions of functions from their older versions. The C++98 standard library includes the C standard library, but it requires the C90 version, which for backwards-compatibility reasons is often not the default for many vendors.
More to the point, the C++ standard requires behavior which is only available on certain platforms after certain symbols are defined. Usually the issue involves I/O-related typedefs. In order to ensure correctness, the compiler simply predefines those symbols.
Note that it's not enough to #define
them only when the library is being built (during installation). Since we don't have an 'export' keyword, much of the library exists as headers, which means that the symbols must also be defined as your programs are parsed and compiled.
To see which symbols are defined, look for CPLUSPLUS_CPP_SPEC
in the gcc config headers for your target (and try changing them to see what happens when building complicated code). You can also run g++ -E -dM - < /dev/null" [sic] to display a list of predefined macros for any particular installation.
This has been discussed on the mailing lists quite a bit.
This method is something of a wart. We'd like to find a cleaner solution, but nobody yet has contributed the time.
说明:
glibc 是提供标准 C 库的软件。它支持多种模式。
它支持各种严格的C模式和严格的POSIX模式。在这些模式中,当只包含标准 headers 时,只有标准功能可用。在 C90 模式下,这不包括 isnan
.
支持多种扩展模式。在这些模式下,non-standard 功能也可用。在 C90 + 扩展模式中,这包括 isnan
。 _GNU_SOURCE
预处理器宏是启用所有扩展的宏。
libstdc++ 是提供标准 C++ 库的东西。它对 glibc 的要求比严格的 C90 模式提供的更多。因此,只有两种选择:要么 libstdc++ 不提供它无法提供的那些标准 C++ 功能,要么 libstdc++ 即使在严格的 ANSI 模式下也强制启用 glibc 的扩展。两者都是不符合C++标准的意思,只是前者限制特性,后者提供特性。后者被视为较小的邪恶。
解决此问题的唯一合理方法是让 glibc 提供一些 non-standard 方法来访问其扩展,即使在严格的 ANSI 模式下也是如此。目前还没有这样的方法,在创建这样的方法之前,即使在 meant-to-be-standard C++ 编译模式下,non-standard 名称也将可用。
我的理解是函数 std::isnan
只能从 C++11 开始使用。此外,g++
使用 -std=gnu++98
除非明确告知不要这样做。
那么为什么要编译?
>> cat test.cpp
#include <cmath>
int main(int argc, char** argv)
{
return std::isnan(0);
}
>> g++ test.cpp
是否有将函数从 <cmath>
中取出的标志?
编译器开发人员懒于完全删除应该只在下一版本标准中可用的每个功能,尤其是当相关库 (C99) 同时具有它时。
实用程序(验证您的代码实际上是否遵守特定标准)不足以让编译器编写者非常努力地让他们的编译器提供该服务。
相反,通常发生的情况是新功能是在特定标准标志下实现的。有时他们会被意外地向后移植。当标准最终确定时,部分实现会存在一段时间,直到它变得足够好。
然后开始制定下一版本的标准。下一个版本标志为您提供了一个不太稳定的开发环境,因为新功能被尝试、丢弃和更改。
它在不向后移植方面付出了一些努力,但它并不是一个引人注目的东西。
这是一个 long-standing 问题,已记录在案 in the FAQ,但您不一定能够理解。
4.3.
_XOPEN_SOURCE
and_GNU_SOURCE
are always defined?On Solaris, g++ (but not gcc) always defines the preprocessor macro
_XOPEN_SOURCE
. On GNU/Linux, the same happens with_GNU_SOURCE
. (This is not an exhaustive list; other macros and other platforms are also affected.)These macros are typically used in C library headers, guarding new versions of functions from their older versions. The C++98 standard library includes the C standard library, but it requires the C90 version, which for backwards-compatibility reasons is often not the default for many vendors.
More to the point, the C++ standard requires behavior which is only available on certain platforms after certain symbols are defined. Usually the issue involves I/O-related typedefs. In order to ensure correctness, the compiler simply predefines those symbols.
Note that it's not enough to
#define
them only when the library is being built (during installation). Since we don't have an 'export' keyword, much of the library exists as headers, which means that the symbols must also be defined as your programs are parsed and compiled.To see which symbols are defined, look for
CPLUSPLUS_CPP_SPEC
in the gcc config headers for your target (and try changing them to see what happens when building complicated code). You can also run g++ -E -dM - < /dev/null" [sic] to display a list of predefined macros for any particular installation.This has been discussed on the mailing lists quite a bit.
This method is something of a wart. We'd like to find a cleaner solution, but nobody yet has contributed the time.
说明:
glibc 是提供标准 C 库的软件。它支持多种模式。
它支持各种严格的C模式和严格的POSIX模式。在这些模式中,当只包含标准 headers 时,只有标准功能可用。在 C90 模式下,这不包括 isnan
.
支持多种扩展模式。在这些模式下,non-standard 功能也可用。在 C90 + 扩展模式中,这包括 isnan
。 _GNU_SOURCE
预处理器宏是启用所有扩展的宏。
libstdc++ 是提供标准 C++ 库的东西。它对 glibc 的要求比严格的 C90 模式提供的更多。因此,只有两种选择:要么 libstdc++ 不提供它无法提供的那些标准 C++ 功能,要么 libstdc++ 即使在严格的 ANSI 模式下也强制启用 glibc 的扩展。两者都是不符合C++标准的意思,只是前者限制特性,后者提供特性。后者被视为较小的邪恶。
解决此问题的唯一合理方法是让 glibc 提供一些 non-standard 方法来访问其扩展,即使在严格的 ANSI 模式下也是如此。目前还没有这样的方法,在创建这样的方法之前,即使在 meant-to-be-standard C++ 编译模式下,non-standard 名称也将可用。