Is isnan in the std:: namespace? More in general, when is std:: necessary, optional or to be avoided?

StackOverflow https://stackoverflow.com/questions/18128899

  •  24-06-2022
  •  | 
  •  

Question

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

Was it helpful?

Solution

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

OTHER TIPS

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 write isnan.

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 write isnan, just like in C.

In addition, when you write #include <cmath> all the names declared in the header go into the namespace std, and you need to write std::isnan.

Further, C++ implementations are allowed to also go the other way, with #include <math.h> putting the names into std as well as in the global namespace, and with #include <cmath> putting the names into the global namespace as well as in std. 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 no isnan in the global namespace and that if you use #include <math.h> you cannot assume that there will be no isnan in std.

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 ]

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top