Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

<cmath> hides isnan in <math.h> in C++14 / C++11?

Tags:

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; } 

Build and run under 3 different standards:

$ 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 

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; } 

Build and run:

C++98 works

$ g++ -std=c++98 main.cpp; ./a.out 1 1 

C++11 and C++14 don't, isnan is not found.

$ 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)      ^ 

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

Questions

  • Why is isnan gone?
  • Without having to go back and change old code to compile under the new standard, is there any way to fix this?
like image 974
Steve Lorimer Avatar asked Aug 24 '16 17:08

Steve Lorimer


People also ask

What is cmath vs math H in C++?

[cmath] defines symbols in the std namespace, and may also define symbols in the global namespace. [math. h] defines symbols in the global namespace, and may also define symbols in the std namespace. if you include the former and use an unqualified symbol, it may compile with one compiler but not with another.

What does cmath include in C++?

The cmath header file contains definitions for C++ for computing common mathematical functions. Include the standard header into a C++ program to effectively include the standard header < math. h > within the std namespace.

Is NaN function C++?

Checking if a double (or float) is NaN in C++ To check whether a floating point or double number is NaN (Not a Number) in C++, we can use the isnan() function. The isnan() function is present into the cmath library. This function is introduced in C++ version 11.


1 Answers

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

  • 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.

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 
like image 127
T.C. Avatar answered Oct 05 '22 02:10

T.C.