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
isnan
gone?[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.
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.
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.
Briefly summarizing the pertinent points, mostly from Jonathan Wakely's excellent blog post:
math.h
declares the obsolete X/Open int isnan(double);
that is incompatible with the C99/C++11 version (bool isnan(double);
).math.h
fixes this by not declaring the isnan
function in C++11 or later.isnan
macro. #include <cmath>
nukes that macro as required by the C++ standard.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.#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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With