我这里有一个小型测试应用程序,它使用isnan
from <math.h>
:
#include <iostream>
#include <math.h>
int main()
{
double d = NAN;
std::cout << isnan(d) << '\n';
return 0;
}
根据 3 种不同的标准构建和运行:
$ g++ -std=c++98 main.cpp; ./a.out
1
$ g++ -std=c++11 main.cpp; ./a.out
1
$ g++ -std=c++14 main.cpp; ./a.out
1
现在我们还包括<cmath>
,并用两者进行测试isnan
and std::isnan
:
#include <iostream>
#include <cmath>
#include <math.h>
int main()
{
double d = NAN;
std::cout << std::isnan(d) << '\n';
std::cout << isnan(d) << '\n';
return 0;
}
构建并运行:
C++98 工作
$ g++ -std=c++98 main.cpp; ./a.out
1
1
C++11 和 C++14 没有,isnan
没有找到。
$ g++ -std=c++11 main.cpp
main.cpp: In function ‘int main()’:
main.cpp:10:25: error: ‘isnan’ was not declared in this scope
std::cout << isnan(d) << '\n';
^
main.cpp:10:25: note: suggested alternative:
In file included from main.cpp:3:0:
/usr/include/c++/5/cmath:641:5: note: ‘std::isnan’
isnan(_Tp __x)
^
$ g++ -std=c++14 main.cpp
main.cpp: In function ‘int main()’:
main.cpp:10:25: error: ‘isnan’ was not declared in this scope
std::cout << isnan(d) << '\n';
^
main.cpp:10:25: note: suggested alternative:
In file included from main.cpp:3:0:
/usr/include/c++/5/cmath:641:5: note: ‘std::isnan’
isnan(_Tp __x)
^
请注意,包含的顺序并不重要。如果我包括<cmath>
before <math.h>
或者之后,结果是一样的。
问题
- Why is
isnan
gone?
- 无需返回并更改旧代码即可在新标准下进行编译,有什么方法可以解决此问题吗?
简单总结一下相关要点,主要来自乔纳森·韦克利 (Jonathan Wakely) 的精彩博客文章 http://developers.redhat.com/blog/2016/02/29/why-cstdlib-is-more-complicated-than-you-might-think/:
- glibc math.h声明过时的 X/Open
int isnan(double);
与 C99/C++11 版本不兼容(bool isnan(double);
).
- glibc 2.23 的
math.h
通过不声明来解决这个问题isnan
C++11 或更高版本中的函数。
- 他们都仍然定义了一个
isnan
macro. #include <cmath>
按照 C++ 标准的要求对该宏进行核武器攻击。
- GCC 6的libstdc++提供了自己特殊的
math.h
声明一个标头bool isnan(double);
在全局命名空间中(除非 libcmath.h
声明过时的签名),并且还按照标准的要求删除宏。
- 在海湾合作委员会 6 之前,
#include <math.h>
只是包含了 libc 中的标头,因此宏不会被破坏。
-
#include <cmath>
总是对宏进行核攻击。
最终结果,在 C++11 模式下:
glibc < 2.23, GCC < 6: <math.h> uses the macro; <cmath> uses obsolete signature
glibc >= 2.23, GCC < 6: <math.h> uses the macro; <cmath> results in error
glibc < 2.23, GCC >= 6: <math.h> and <cmath> use obsolete signature
glibc >= 2.23, GCC >= 6: <math.h> and <cmath> use standard signature
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)