Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

like image 534
Antonio Avatar asked Aug 08 '13 14:08

Antonio


2 Answers

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 ]

like image 157
Yu Hao Avatar answered Sep 30 '22 14:09

Yu Hao


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

like image 45
Christian Rau Avatar answered Sep 30 '22 12:09

Christian Rau