In C++, std::abs is overloaded for both signed integer and floating point types. std::fabs only deals with floating point types (pre C++11). Note that the std:: is important; the C function ::abs that is commonly available for legacy reasons will only handle int!
The problem with
Copyfloat f2= fabs(-9);
is not that there is no conversion from int (the type of -9) to double, but that the compiler does not know which conversion to pick (int -> float, double, long double) since there is a std::fabs for each of those three. Your workaround explicitly tells the compiler to use the int -> double conversion, so the ambiguity goes away.
C++11 solves this by adding double fabs( Integral arg ); which will return the abs of any integer type converted to double. Apparently, this overload is also available in C++98 mode with libstdc++ and libc++.
In general, just use std::abs, it will do the right thing. (Interesting pitfall pointed out by @Shafik Yaghmour. Unsigned integer types do funny things in C++.)
In C++, std::abs is overloaded for both signed integer and floating point types. std::fabs only deals with floating point types (pre C++11). Note that the std:: is important; the C function ::abs that is commonly available for legacy reasons will only handle int!
The problem with
Copyfloat f2= fabs(-9);
is not that there is no conversion from int (the type of -9) to double, but that the compiler does not know which conversion to pick (int -> float, double, long double) since there is a std::fabs for each of those three. Your workaround explicitly tells the compiler to use the int -> double conversion, so the ambiguity goes away.
C++11 solves this by adding double fabs( Integral arg ); which will return the abs of any integer type converted to double. Apparently, this overload is also available in C++98 mode with libstdc++ and libc++.
In general, just use std::abs, it will do the right thing. (Interesting pitfall pointed out by @Shafik Yaghmour. Unsigned integer types do funny things in C++.)
With C++ 11, using abs() alone is very dangerous:
Copy#include <iostream>
#include <cmath>
int main() {
std::cout << abs(-2.5) << std::endl;
return 0;
}
This program outputs 2 as a result. (See it live)
Always use std::abs():
Copy#include <iostream>
#include <cmath>
int main() {
std::cout << std::abs(-2.5) << std::endl;
return 0;
}
This program outputs 2.5.
You can avoid the unexpected result with using namespace std; but I would adwise against it, because it is considered bad practice in general, and because you have to search for the using directive to know if abs() means the int overload or the double overload.
fabs versus abs? - C++ Forum
c++ - When do I use fabs and when is it sufficient to use std::abs? - Stack Overflow
What does the function "fabs(_:)" … | Apple Developer Forums
abs function equivalent in c++
In C++, it's always sufficient to use std::abs; it's overloaded for all the numerical types.
In C, abs only works on integers, and you need fabs for floating point values. These are available in C++ (along with all of the C library), but there's no need to use them.
It's still okay to use fabs for double and float arguments. I prefer this because it ensures that if I accidentally strip the std:: off the abs, that the behavior remains the same for floating point inputs.
I just spent 10 minutes debugging this very problem, due to my own mistake of using abs instead of std::abs. I assumed that the using namespace std;would infer std::abs but it did not, and instead was using the C version.
Anyway, I believe it's good to use fabs instead of abs for floating-point inputs as a way of documenting your intention clearly.