views:

273

answers:

3

Hello, while doing some homework in my very strange C++ book, which I've been told before to throw away, had a very peculiar code segment. I know homework stuff always throws in extra "mystery" to try to confuse you like indenting 2 lines after a single-statement for-loop. But this one I'm confused on because it seems to serve some real-purpose.

basically it is like this:

int counter=10;
...
if(pow(floor(sqrt(counter+0.0)),2) == counter)
...

I'm interested in this part especially:

sqrt(counter+0.0)

Is there some purpose to the +0.0? Is this the poormans way of doing a static cast to a double? Does this avoid some compiler warning on some compiler I do not use? The entire program printed the exact same thing and compiled without warnings on g++ whenever I left out the +0.0 part. Maybe I'm not using a weird enough compiler?

Edit:

Also, does gcc just break standard and not make an error for Ambiguous reference since sqrt can take 3 different types of parameters?

[earlz@EarlzBeta-~/projects/homework1] $ cat calc.cpp
#include <cmath>

int main(){
  int counter=0;
  sqrt(counter);
}
[earlz@EarlzBeta-~/projects/homework1] $ g++ calc.cpp
/usr/lib/libstdc++.so.47.0: warning: strcpy() is almost always misused, please use strlcpy()
/usr/lib/libstdc++.so.47.0: warning: strcat() is almost always misused, please use strlcat()
[earlz@EarlzBeta-~/projects/homework1] $

Also, here is the relevant part of my system libraries cmath I'm not too keen on templates, so I'm not sure what it's doing

  using ::sqrt;

  inline float
  sqrt(float __x)
  { return __builtin_sqrtf(__x); }

  inline long double
  sqrt(long double __x)
  { return __builtin_sqrtl(__x); }

  template<typename _Tp>
    inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value,
                       double>::__type
    sqrt(_Tp __x)
    { return __builtin_sqrt(__x);
+12  A: 

Is this the poormans way of doing a static cast to a double?

Yes.

You can't call sqrt with an int as its parameter, because sqrt takes a float, double, or long double. You have to cast the int to one of those types, otherwise the call is ambiguous.

James McNellis
but why? it's not even necessary in this case.
Earlz
@Earlz: I don't know why anyone would recommend using `+ 0.0`. The only thing it has going for it is that it's less to type than `static_cast<double>` or `(double)`, but that's not a good reason to use it.
James McNellis
@James why does g++ not give an error or warning about this then? See my edit.
Earlz
@James, yeah, but even an explicit cast isn't necessary. Implicit conversion should take care of it.
Derrick Turk
For your guys information this is actually a way most book writers teach to cast a int into a double. As Precision Math added to Interger Math defaults to Precision.
AjayP
Also what the book is looking out for is if you modify the code to make counter taken from user input it would automatically cast it.
AjayP
The reason you don't get a warning is because the compiler is satisfied. It wants a double and it gets a double. The difference between adding 0.0 and explicitly casting using the C++ `static_cast` operator is that the latter approach is very explicit. No one would ask "what are you doing" in that case (as opposed to adding 0.0, which is herein demonstratedly unclear).
wilhelmtell
Data points: Without a cast of some sort (or forcing the expression to be of type double) MSVC 2003 or later and Comeau generate an error; GCC 3.4.5, Digital Mars and MSVC 6 do not. I wonder how the later decide to resolve the overload?
Michael Burr
@Earlz: I don't know why g++ accepts your trivial example, unless you don't have the additional overloads for `float` and `long double` in your standard library. Visual C++ and Comeau both rightly reject the example code due to the overload ambiguity.
James McNellis
@Michael. Ah, I compile all my homework code with g++, so guess this is why I didn't catch it. So apparently this guy couldn't write `static_cast<double>(counter)` and instead had to leave code to the student to figure out... which he never talked about this trick specifically in the book.
Earlz
@James, well the overloaded ones must not be part of the ANSI standard (and therefore, not included in the "standard libraries") cause with the most up to date gcc, it compiles fine without warnings.
Earlz
@Earlz: The overloads are all part of the C++ standard library and have been since the language was standardized. In the C standard library they have different names (since they have to): `sqrtf`, `sqrt`, and `sqrtl`. You can find out pretty easily by looking in your `cmath` header.
James McNellis
@Michael Burr: In the standard library that came with VC 6 the overloaded versions of `sqrt` (and other C-style math functions) are disabled by defualt by a macro. I don't remember the name of the macro, but in any case this is why VC 6 does not complain. In VC 6 by default `sqrt` works the same way it worked in C - it expects `double` and only `double`. No overloads.
AndreyT
@James, so did gcc violate the standard then? See my edit for my cmath file.
Earlz
@Earlz: It explains why there is no overload ambiguity. The function template is used to select the `sqrt(double)` overload if the argument is of an integer type. I don't think that _violates_ the library standard (it _might_, but I doubt it). It's certainly an implementation-specific addition though, and relying on it would be a bad idea if you are trying to write portable code.
James McNellis
@James. ok, good to know. I Guess that's what I get for only using g++ and glibc :P
Earlz
Personally, I think that this + 0.0 business is crazy. I thought everybody knew that you should multiply by 1.0 in a situation like this.
Michael Daum
@Michael. what? I was always under the impression to just suck it up and do a static_typecast or at least a C-style cast.
Earlz
A: 

the reason for the expression counter + 0.0 is to explicitly make it a real number. if we donot add 0.0 the compiler will do implicit conversion

Grv
A: 

It's just another way to cast to a double. This is because sqrt doesn't accept ints. Because a double is higher it will merge the int into the 0.0. The same way can be done for converting from (int,double,float) to string.

double n = 0;

string m = ""+n;

flopex
I think you are thinking of some other programming language; you can't do that in C++.
James McNellis