The following c++ code does not compile:
int main() {
double a = abs(5.1);
return 0;
}
It complains that abs
is not defined, of course. But the following does compile:
#include <iostream>
int main() {
std::cout << abs(5.1) << std::endl;
std::cout << abs(-5.1) << std::endl;
return 0;
}
It outputs two 5's (not 5.1's). This is bad for lots of reasons. First, abs
is such a natural and common function that I use it all the time, but the int
part is almost never what I want returned. Second, it's much too easy for me (or people using my code) to just write abs
and not notice that it compiles but does the wrong thing, because I'm (they're) really good at overlooking warnings. Third, I just plain don't understand why iostream bothers defining an abs
function anyway. Fourth, I really don't understand why it goes into the global namespace.
Is there any way I can prevent this objectionable abs
function from going into my global namespace?
If it matters, I'm using
gcc version 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.6)
The abs() function in C++ returns the absolute value of the argument. It is defined in the cmath header file. Mathematically, abs(num) = |num| .
The abs() in C++ returns the absolute value of an integer number. If the number is negative, it will return the positive value (with the same magnitude), for example, abs(-1) = 1. If the number is already positive or zero, it will return the number as it is, for example, abs(1) = 1.
Special behavior for C++: For C++ applications, abs() is also overloaded for the types long, float, and long double.
std::abs(float), std::fabs, std::fabsf, std::fabsl. 1-8) Computes the absolute value of a floating point value arg .
In C, including one standard header was not allowed to act like it included any other standard header. This avoided the problem you're seeing, at considerable expense in difficulty implementation.
C++ allows any standard header to include any other standard header. This makes implementation considerably easier, but can lead to exactly the sort of problem you're seeing, where including a seemingly-unrelated header has made a function visible that you didn't really want to use, instead of getting an error because the function you used isn't declared at all.
Unfortunately, I don't think there's an easy way to deal with this. Although it's pretty easy to imagine <iostream>
being independent of <stdlib.h>
, it's much easier to see how it might need/want definitions of things like ios_base
. It would take quite a bit of extra work to define things to prohibit the former while allowing the latter.
I should mention, however, that over time this situation does seem to be improving quite a bit. Ten years ago, it was fairly common to get virtually all standard headers from including almost any one of them. Although most still include at least a few that aren't strictly required, they're generally much closer to each defining only what it's required to.
Most likely iostream
includes stdlib.h
to do some of its work. This is the C version of the header which declares abs
for int
only in the global namespace (in C you had to use fabs
for double
values).
I'm not aware of any specific way to keep abs
from being included that way but I do know that g++ 4.5 is much better at not having excess stuff brought in by basic includes like iostream
and string
.
It may also be possible to get a warning that the double is being truncated to int (EDIT: yes, use -Wconversion
to warn).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With