0

i just stumbled upon a really crazy bug after over a year since writing a program (it hit an assertion) regarding abs(). i'll spare you the details and i'll just show you what i don't understand here:

gcc version 7.5.0 on xubuntu_x64:

#include <stdlib.h>

int _test_abs(int x) {
    return abs((unsigned)x);
}

try to compile this and the compiler starts complaining about "call to abs(unsigned int) is ambiguous", and lists as candidates abs(int), abs(long), abs(float), you name it (but no abs(unsigned) appears anywhere, which is expected - else there would be no ambiguity)

now replace <stdlib.h> with <cstdlib> and everythig compiles ok w/ NO errors. how on earth does it NOT complain about ambiguities in this case? is there somewhere in <cstdlib> an abs(unsigned) declared? i couldn't find any info about such a signature in <cmath>

the same happens with <math.h> vs <cmath>.

can anyone enlighten me on this one?

PS what my bug was all about: i am frequently using unsigneds when it's about unsigned quantities, but i accept having expressions in my code such as (unsig1-unsig2) which may occasionally be negative (i.e. unsig2 is slightly larger than unsig1), but i use directly abs(unsig1-unsig2) without bothering to convert to abs((int)(unsig1-unsig2) because it SHOULD be okay, the value would be converted to 'int' when abs(int) is called, and abs should indeed return the correct absolute value. What i was not aware of is that abs(int) was actually never called in my program, but rather the abs(float) version (or double or long double or whatever) was used, and in this case the result from converting my unsigned expression (unsig1-unsig2) with unsig2 slightly > unsig1 to float is a huge unsigned value instead of a small "negative unsigned"! bottom line, i was expecting a behavior from abs(int), but instead abs(float) was actually being called and gave me crazy unexpected results.

PPS fwiw, an interesting article i ran into during my little "investigation", apparently abs() is a total mess: https://developers.redhat.com/blog/2016/02/29/why-cstdlib-is-more-complicated-than-you-might-think/

Gyll
  • 351
  • 2
  • 6

1 Answers1

0

After some inspector clouseau detective work, i came up with one possible answer: maybe <cmath> and <cstdlib> define only "abs(int)' in the global namespace, while the full set of declarations (int + overloads) are defined exclusively in 'std::". This possibility is upheld by the fact that if you use <cmath>/<cstdlib> in the code above and you change the call into "std::abs()" then you get the "ambiguous" error (i.e. when searching inside the "std::" namespace with <cmath>/<cstdib> included, then both the int and the overloaded versions are found, hence the error).

Does anyone know if this is indeed the case (w/ link to the source of your info pls)?

PS whatever the case, what is clear is that it's a mess, because even if this answer is correct, there is no standard requirement for this implementation (at least up to, and including c++11, see the link in the OP)

Gyll
  • 351
  • 2
  • 6