< cmath>在< math.h>中隐藏isnan在C ++ 14/C ++ 11中? [英] <cmath> hides isnan in <math.h> in C++14 / C++11?

查看:127
本文介绍了< cmath>在< math.h>中隐藏isnan在C ++ 14/C ++ 11中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在这里有一个小型测试应用程序,它使用< math.h> 中的 isnan :

I have here a small test app which uses 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 std :: isnan :

Now we also include <cmath>, and test with both 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)
     ^

请注意,包含顺序并不重要.如果我在< math.h> 之前或之后加上< cmath> ,则结果是相同的.

Note the order of inclusion is not important. If I include <cmath> before <math.h> or after, the result is the same.

问题

  • 为什么 isnan 不见了?
  • 无需回去更改旧代码即可在新标准下进行编译,有什么方法可以解决此问题?

推荐答案

简要总结相关点,主要来自

Briefly summarizing the pertinent points, mostly from Jonathan Wakely's excellent blog post:

  • glibc< 2.23的 math.h 声明了与C99/C ++ 11版本不兼容的过时的X/Open int isnan(double); ( bool isnan(double); ).
  • glibc 2.23的 math.h 通过不声明C ++ 11或更高版本中的 isnan 函数来解决此问题.
  • 所有这些都仍然定义了 isnan 宏. #include< cmath> 会按照C ++标准的要求更改该宏.
  • GCC 6的libstdc ++提供了其自己的特殊 math.h 头,该头在全局命名空间中声明了 bool isnan(double); (除非libc math).h 声明过时的签名),并按标准要求对宏进行修改.
  • 在GCC 6之前, #include< math.h> 只是包含了libc中的标头,因此该宏不会被破坏.
  • #include< cmath> 总是对宏进行操作.
  • glibc <2.23's math.h declares the obsolete X/Open int isnan(double); that is incompatible with the C99/C++11 version (bool isnan(double);).
  • glibc 2.23's math.h fixes this by not declaring the isnan function in C++11 or later.
  • All of them still define an isnan macro. #include <cmath> nukes that macro as required by the C++ standard.
  • GCC 6's libstdc++ provides its own special math.h header that declares a bool isnan(double); in the global namespace (unless the libc math.h declares the obsolete signature) and also nukes the macros as required by the standard.
  • Before GCC 6, #include <math.h> simply included the header from your libc, so the macro isn't nuked.
  • #include <cmath> always nukes the macros.

在C ++ 11模式下的最终结果:

Net result, in C++11 mode:

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

这篇关于&lt; cmath&gt;在&lt; math.h&gt;中隐藏isnan在C ++ 14/C ++ 11中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆