g++ error: call of overloaded 'abs(unsigned int)' is ambiguous
Solution 1
You can just cast the result to a signed datatype for abs to know which one you're calling like this:
while( abs( int(res1 - res2) ) > 1 )
but rethink again of what you need to do here as the result of minus operation on unsigned is still unsigned, so if the result goes below 0 it will turn to be a great number (as a normal overflow), so I think the use of signed variables is the best way to solve the issue in the first place
int iSqr( unsigned i )
{
int res1 = 2;
int res2 = i/res1;
while( abs(res1 - res2) > 1 )
{
res1 = (res1 + res2)/2;
res2 = i/res1;
}
return res1 < res2 ? res1 : res2;
}
Solution 2
abs
in <stdlib.h>
(since c++11): http://www.cplusplus.com/reference/cstdlib/abs/
int abs ( int n);
long int abs ( long int n);
long long int abs (long long int n);
The call will be ambiguous if overload resolution cannot select a match to the call that is uniquely better than such undifferentiable functions.
You can cast the argument explicitly like:
static_cast<int>(res1 - res2)
Solution 3
Edit: <cstdlib>
should handle the overloads (and should be preferred anyways), see the question here
Note that there are some logic errors here. First of all, what you are doing is probably not what you want. res1 - res2
is arithmetic between two unsigned
types, and so the result is also going to be unsigned
. If you go below 0, you wrap back to max int. abs()
is pointless here, that value will never be negative because the type disallows it. Even with the header that compiles this code, the compiler will still warn about this.
I highly recommend you stick to signed integers when dealing with arithmetic to avoid these pitfalls, and if you really need the storage, use 64-bit integers.
So my real answer would be, switch unsigned
to int
Also note: unsigned res2 = i / res1;
res2 will be truncated towards 0 here, I'm not sure if that is what you want or not.
Comments
-
Luke 10X almost 2 years
I am trying to compile the following code:
#include <stdlib.h> static unsigned iSqr( unsigned i ) { unsigned res1 = 2; unsigned res2 = i/res1; while( abs( res1 - res2 ) > 1 ) { res1 = (res1 + res2)/2; res2 = i/res1; } return res1 < res2 ? res1 : res2; }
using
g++ test.cc -o test
.However, g++ compiler fails with the following error:
test.cc: In function 'unsigned int iSqr(unsigned int)': test.cc:8:29: error: call of overloaded 'abs(unsigned int)' is ambiguous while( abs( res1 - res2 ) > 1 ) ^ In file included from /usr/include/c++/6/cstdlib:75:0, from /usr/include/c++/6/stdlib.h:36, from test.cc:2: /usr/include/stdlib.h:735:12: note: candidate: int abs(int) extern int abs (int __x) __THROW __attribute__ ((__const__)) __wur; ^~~ In file included from /usr/include/c++/6/stdlib.h:36:0, from test.cc:2: /usr/include/c++/6/cstdlib:185:3: note: candidate: __int128 std::abs(__int128) abs(__GLIBCXX_TYPE_INT_N_0 __x) { return __x >= 0 ? __x : -__x; } ^~~ /usr/include/c++/6/cstdlib:180:3: note: candidate: long long int std::abs(long long int) abs(long long __x) { return __builtin_llabs (__x); } ^~~ /usr/include/c++/6/cstdlib:172:3: note: candidate: long int std::abs(long int) abs(long __i) { return __builtin_labs(__i); } ^~~
Why this error is happening and how to fix it?
g++ version is: gcc version 6.3.0
-
Luke 10X almost 6 yearsCould you please specify how exactly I should amend the code, to make it use signed integers?
-
Luke 10X almost 6 yearsPerhaps
while ( abs( long(res1 - res2) ) > 1 )
would be safer, asres1 - res2
could result in something that is higher than max signed int? -
Khaled Mohamed almost 6 yearsIn C++ long is a 32-bit container just as int ranging from -2,147,483,648 to 2,147,483,647. But you're correct for sure, it's safer to use 'long long' to avoid overflowing as it's the 64-bit container. Also don't forget that it'll still overflow if res1 and res2 are unsigned if it goes below 0, as the result is put in a container as the operands of the operation.
-
ricco19 almost 6 yearsAlso in c++ it's recommended to use c++ style casts, ie
static_cast<long>(res1 - res2)
over the c style. I still prefer just usingint
s everywhere here though. -
Chen Li almost 6 yearslong is not guarantee to be 32-bit
-
Khaled Mohamed almost 6 yearsActually in most environments it will be 32-bit so it's safer to use long long if what we need is a "certain" 64-bit container to avoid overflowing @陳力
-
ricco19 almost 6 yearsI believe
long
is required to be at least 32 bits? It's usually the same size asint
though. Personally I always use fixed width integers if I require a specific capacity. -
Chen Li almost 6 yearsThe language and its implementation are different things. So, you can say
in most environments it will be 32-bit
, but you can't sayIn C++ long is a 32-bit
-
ricco19 almost 6 yearsIs it implementation defined? If it's required by the standard then the implementation is non-compliant, and the size of no data types should be trusted.