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).
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, likeisnan
. 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 thestd
namespace and thus you have to properly qualify them, likestd::isnan
(or use some kind ofusing
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 useisnan
or include<cmath>
and usestd::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 theisnan
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).That's because
isnan
is from C. Using different type ofinclude
will lead to different results. Takeisnan
from C header<math.h>
as an example:If you use
#include <cmath>
, it will be put in thestd
namespace.If you use
#include <math.h>
, it will be put in the global namespace.C++11 D.5 C standard library headers
C has no notion of namespaces. When you write
#include <math.h>
all the names declared in the header go into the global namespace, and you need to writeisnan
.C++ has namespaces. Still, when you write
#include <math.h>
all the names declared in the header go into the global namespace, and you need to writeisnan
, just like in C.In addition, when you write
#include <cmath>
all the names declared in the header go into the namespacestd
, and you need to writestd::isnan
.Further, C++ implementations are allowed to also go the other way, with
#include <math.h>
putting the names intostd
as well as in the global namespace, and with#include <cmath>
putting the names into the global namespace as well as instd
. Don't rely on this; code that does so is not portable. This is a concession to implementors to make things easier; what it really means is that if you use#include <cmath>
you cannot assume that there will be noisnan
in the global namespace and that if you use#include <math.h>
you cannot assume that there will be noisnan
instd
.