Luke 10X
Luke 10X

Reputation: 1410

g++ error: call of overloaded 'abs(unsigned int)' is ambiguous

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

Upvotes: 3

Views: 17148

Answers (3)

Li Chen
Li Chen

Reputation: 5270

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)

Upvotes: 6

ricco19
ricco19

Reputation: 743

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.

Upvotes: 4

Khaled Mohamed
Khaled Mohamed

Reputation: 406

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;
}

Upvotes: 5

Related Questions