From: Dave Steffen on 3 Jan 2008 06:29 Hi Folks, I came across an annoying thing: the 'isnan' function isn't a function, it's actually a macro (at least on my Linux system), defined in math.h. In principle, the notion was IIRC that #include <math.h> pulls the contents of math.h into the global namespace (a la C), while <cmath> pulls the contents into namespace std. Of course, you can't pull a macro (nasty things) into namespaces at all. Does the standard say anything about what #include <cmath> does to macros (he asks, expecting the answer 'no). What I'd like to do is arrange for 'isnan' to actually act like a function, so I can provide overloaded versions to handle some locally-grown numeric types. One possibility: #include <cmath> namespace detail { bool isNaN(double d) { return isnan(d); } } #undef isnan namespace myNameSpace{ bool isnan(double d) { return detail::isNaN(d); } } // carry on using isnan on doubles and providing overloads for other // things Comments? Notions? Half-baked ideas? Thanks! -- Dave Steffen - Software Engineer 4 Numerica Corporation (www.numerica.us <http://www.numerica.us/> ) [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Bob on 3 Jan 2008 08:31 Dave Steffen wrote: > > Hi Folks, > > I came across an annoying thing: the 'isnan' function isn't a > function, it's actually a macro (at least on my Linux system), defined > in math.h. isnan() is also a macro, according to the 1999 C standard. I haven't checked if that is so in the 1989/90 C standard. > > In principle, the notion was IIRC that #include <math.h> pulls the > contents of math.h into the global namespace (a la C), while <cmath> > pulls the contents into namespace std. That clearly does not work with macros, as macros do not respect scope. Once the preprocessor has done it's job, the macro no longer exists as far as the compiler is concerned. > > Of course, you can't pull a macro (nasty things) into namespaces at > all. Does the standard say anything about what #include <cmath> does > to macros (he asks, expecting the answer 'no). > > What I'd like to do is arrange for 'isnan' to actually act like a > function, so I can provide overloaded versions to handle some > locally-grown numeric types. One possibility: > > #include <cmath> > namespace detail { > bool isNaN(double d) { return isnan(d); } > } > > #undef isnan > namespace myNameSpace{ > bool isnan(double d) { return detail::isNaN(d); } > } > > // carry on using isnan on doubles and providing overloads for other > // things > > Comments? Notions? Half-baked ideas? Thanks! You actually have a few issues here, not least of which is that floating point types are not actually required to be able to represent a NaN value (eg if your compiler does not support IEEE formats). In any event, the std::numeric_limits class (within <limits> includes facilities related to detecting if a "real" type supports NaN. Using a similar approach you would be able to provide your IsNaN() function as a template, which is specialised appropriately for your types. More generally, a common practical reason for wanting to detect NaN's is that you have numerical code that can generate them. I would suggest one option is to modify that code so it detects the conditions that would *result* in a NaN and give an error return code of some form. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Alberto Ganesh Barbati on 4 Jan 2008 14:51 Dave Steffen ha scritto: > Hi Folks, > > I came across an annoying thing: the 'isnan' function isn't a > function, it's actually a macro (at least on my Linux system), defined > in math.h. Correct, C99 requires isnan() to be a macro. > In principle, the notion was IIRC that #include <math.h> pulls the > contents of math.h into the global namespace (a la C), while <cmath> > pulls the contents into namespace std. That is incorrect. First of all, the standard library of C++03 makes reference to the C library of C90, not of C99. I don't have C90 at hand, but I guess isnan() was not present in C90. So, in order for this discussion to make sense, we have to consider the next revision of C++, which makes reference to C99 and mentions isnan() explicitly. Please notice that in C++ <math.h> is defined in terms of <cmath> and not viceversa. This means that the <math.h> in C++ may be different from the <math.h> in C, in the sense that they do not necessarily define the same things (how this is achieved on a shared C/C++ implementation, whether by using two different files, by relying on the pre-processor or by any other mean, is unspecified). Actually, according to latest draft of C++0X, <cmath> shall define (in namespace std) several things with the same meaning as in the C99 <math.h>, but *not* all of it and also adds several things. In particular, <cmath> shall *not* define a macro named isnan() nor any of the other is*() macros. On the contrary, isnan() is defined to be a template. > Of course, you can't pull a macro (nasty things) into namespaces at > all. Does the standard say anything about what #include <cmath> does > to macros (he asks, expecting the answer 'no). C++0X (which is not yet a standard!) says explicitly that <cmath> shall not define is*() as macros but as templates in section 26.7/12: "The templates defined in <cmath> replace the C99 macros with the same names. The templates have the following declarations: namespace std { template <class T> bool signbit(T x); template <class T> int fpclassify(T x); template <class T> bool isfinite(T x); template <class T> bool isinf(T x); template <class T> bool isnan(T x); template <class T> bool isnormal(T x); template <class T> bool isgreater(T x, T y); template <class T> bool isgreaterequal(T x, T y); template <class T> bool isless(T x, T y); template <class T> bool islessequal(T x, T y); template <class T> bool islessgreater(T x, T y); template <class T> bool isunordered(T x, T y); } // namespace std" > What I'd like to do is arrange for 'isnan' to actually act like a > function, so I can provide overloaded versions to handle some > locally-grown numeric types. One possibility: > > #include <cmath> > namespace detail { > bool isNaN(double d) { return isnan(d); } > } > > #undef isnan > namespace myNameSpace{ > bool isnan(double d) { return detail::isNaN(d); } > } > > // carry on using isnan on doubles and providing overloads for other > // things > > Comments? Notions? Half-baked ideas? Thanks! > I don't know the rationale of providing templates rather than overloads. Anyway, C++0X achieves your goal without messing with macros. HTH, Ganesh -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: P.J. Plauger on 5 Jan 2008 00:42 "Alberto Ganesh Barbati" <AlbertoBarbati(a)libero.it> wrote in message news:vOyfj.214763$U01.1393855(a)twister1.libero.it... > Dave Steffen ha scritto: >> Hi Folks, >> >> I came across an annoying thing: the 'isnan' function isn't a >> function, it's actually a macro (at least on my Linux system), defined >> in math.h. > > Correct, C99 requires isnan() to be a macro. > >> In principle, the notion was IIRC that #include <math.h> pulls the >> contents of math.h into the global namespace (a la C), while <cmath> >> pulls the contents into namespace std. > > That is incorrect. It's correct, just not complete. > First of all, the standard library of C++03 makes reference to the C > library of C90, No, C95. > not of C99. I don't have C90 at hand, but I guess > isnan() was not present in C90. So, in order for this discussion to make > sense, we have to consider the next revision of C++, which makes > reference to C99 and mentions isnan() explicitly. Or you can consider TR1, which already includes isnan a la C99. It's not a required standard, but it is a widely supported Technical Report. And most of it (including the isnan bit) has already been voted into C++0X. > Please notice that in C++ <math.h> is defined in terms of <cmath> and > not viceversa. In principle, but rarely in practice. C++0X has already accepted current practice as future principle. > This means that the <math.h> in C++ may be different > from > the <math.h> in C, in the sense that they do not necessarily define the > same things (how this is achieved on a shared C/C++ implementation, > whether by using two different files, by relying on the pre-processor or > by any other mean, is unspecified). Aside from some tinkering with a handful of function declarations, the primary difference is that C++ disallows masking macros for C functions. > Actually, according to latest draft of C++0X, <cmath> shall define (in > namespace std) several things with the same meaning as in the C99 > <math.h>, but *not* all of it and also adds several things. In > particular, <cmath> shall *not* define a macro named isnan() nor any of > the other is*() macros. On the contrary, isnan() is defined to be a > template. > >> Of course, you can't pull a macro (nasty things) into namespaces at >> all. Does the standard say anything about what #include <cmath> does >> to macros (he asks, expecting the answer 'no). > > C++0X (which is not yet a standard!) says explicitly that <cmath> shall > not define is*() as macros but as templates in section 26.7/12: Yes, this is an analytic continuation of the "no masking macros" rule from C++98. > "The templates defined in <cmath> replace the C99 macros with the same > names. The templates have the following declarations: > namespace std { > template <class T> bool signbit(T x); > template <class T> int fpclassify(T x); > template <class T> bool isfinite(T x); > template <class T> bool isinf(T x); > template <class T> bool isnan(T x); > template <class T> bool isnormal(T x); > template <class T> bool isgreater(T x, T y); > template <class T> bool isgreaterequal(T x, T y); > template <class T> bool isless(T x, T y); > template <class T> bool islessequal(T x, T y); > template <class T> bool islessgreater(T x, T y); > template <class T> bool isunordered(T x, T y); > } // namespace std" > >> What I'd like to do is arrange for 'isnan' to actually act like a >> function, so I can provide overloaded versions to handle some >> locally-grown numeric types. One possibility: >> >> #include <cmath> >> namespace detail { >> bool isNaN(double d) { return isnan(d); } >> } >> >> #undef isnan >> namespace myNameSpace{ >> bool isnan(double d) { return detail::isNaN(d); } >> } >> >> // carry on using isnan on doubles and providing overloads for other >> // things >> >> Comments? Notions? Half-baked ideas? Thanks! >> > > I don't know the rationale of providing templates rather than overloads. There's a rather widespread practice of templatizing on floating-point types. See, e.g. complex. > Anyway, C++0X achieves your goal without messing with macros. Yes. P.J. Plauger Dinkumware, Ltd. http://www.dinkumware.com -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Alberto Ganesh Barbati on 5 Jan 2008 07:59 P.J. Plauger ha scritto: > "Alberto Ganesh Barbati" <AlbertoBarbati(a)libero.it> wrote in message > news:vOyfj.214763$U01.1393855(a)twister1.libero.it... > >> Please notice that in C++ <math.h> is defined in terms of <cmath> and >> not viceversa. > > In principle, but rarely in practice. C++0X has already accepted > current practice as future principle. I meant that the standard first defines what <cmath> is and then defines <math.h> in terms of the former (in D.5 to be precise). Once you have defined what they should do, how the implementation achieves that, either by having <cmath> include <math.h> or viceversa or any other mean, is left unspecified. >> >> I don't know the rationale of providing templates rather than overloads. > > There's a rather widespread practice of templatizing on floating-point > types. See, e.g. complex. Hmmm... Then why are all the other mathematical functions not templated too? I mean, if what you say was the only reason, we should also have template versions of sin(), cos() and abs() or at least of all the new functions introduced in C++0X, if backward compatibility is a concern. BTW, while looking at the draft, I realized that function nan() is provided only in the double "flavor". This means it's impossible to get the functionalities of nanf() and nanl(). Notice that all three functions take a const char* argument so they are unsuitable for overloading. std::numeric_limits<> is not a perfect replacement in this case also because of the const char* argument. In this case, it would make perfect sense to define nan() as a template, for example like this: template <class T = double> T nan(const char*); Any idea why this wasn't considered? Ganesh -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
|
Next
|
Last
Pages: 1 2 Prev: problem of using stream to serialize vector<vector<T> > Next: composition and bad_alloc |