With Mingw 4.7.2, I have a library that doesn't compile because of a call to isnan
.
The compiler says "everything will be fine" if I use std::isnan
, and indeed I manage to compile my file.
But if I check here (Edit: but maybe I should have checked also here :-) ), the std::
doesn't seem to be necessary. If I add it, will the file be portable?
More in general, for each case is there a general way to understand when putting std::
is necessary (for portability), optional or to be avoided?
Edit
Indeed among the origins of the problem is that there are multiple header inclusions, and some of the included headers include <cmath>
, while this cpp file tries to include <math.h>
(when <cmath>
has already been included).
That's because isnan
is from C. Using different type of include
will lead to different results. Take isnan
from C header <math.h>
as an example:
If you use #include <cmath>
, it will be put in the std
namespace.
If you use #include <math.h>
, it will be put in the global namespace.
C++11 D.5 C standard library headers
Every C header, each of which has a name of the form name.h, behaves as if each name placed in the standard library namespace by the corresponding cname header is placed within the global namespace scope. It is unspecified whether these names are first declared or defined within namespace scope (3.3.6) of the namespace std and are then injected into the global namespace scope by explicit using-declarations (7.3.3).
[ Example: The header assuredly provides its declarations and definitions within the namespace std. It may also provide these names within the global namespace. The header assuredly provides the same declarations and definitions within the global namespace, much as in the C Standard. It may also provide these names within the namespace std. —end example ]
It depends on which header you include. If you include the C header <math.h>
(which is part of C++, albeit marked as deprecated), then you can use the unqualified C functions, like isnan
. If you on the other hand include the C++ header <cmath>
, you are only guaranteed that it brings all the functions from <math.h>
into the std
namespace and thus you have to properly qualify them, like std::isnan
(or use some kind of using
directive). Unfortunately an implementation is allowed but not required to bring those functions into the global namespace, too, when including <cmath>
(and thus it is one of the many "works on my machine"-incidences of C++ and the reason why many people write code like you just tried to compile unsuccessfully).
So to sum up: Either include <math.h>
and use isnan
or include <cmath>
and use std::isnan
, everything else is non-portable. Of course all this applies to any other C header and its respective C++ version, too.
EDIT: It should be noted though, that this particular function isnan
is only supported since C++11 and wasn't available in C++98 at all (which may be part of your confusion). But this doesn't change anything in this situation because in C++98 neither <cmath>
nor <math.h>
(which was the actual C89/C90 header back then and not the C99 header that C++11 includes) had this function, since they're always in-sync. So what this library from your question maybe tried was to use C++98 while taking the isnan
function from a different C99 implementation (which isn't a particularly good idea, as it might conflict with the C89/C90 parts of the C++ implementation, never even tried this though).
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