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

10,314

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.

Share:
10,314
Luke 10X
Author by

Luke 10X

Node.js/React/Typescript + Java

Updated on June 04, 2022

Comments

  • Luke 10X
    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
    Luke 10X almost 6 years
    Could you please specify how exactly I should amend the code, to make it use signed integers?
  • Luke 10X
    Luke 10X almost 6 years
    Perhaps while ( abs( long(res1 - res2) ) > 1 ) would be safer, as res1 - res2 could result in something that is higher than max signed int?
  • Khaled Mohamed
    Khaled Mohamed almost 6 years
    In 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
    ricco19 almost 6 years
    Also in c++ it's recommended to use c++ style casts, ie static_cast<long>(res1 - res2) over the c style. I still prefer just using ints everywhere here though.
  • Chen Li
    Chen Li almost 6 years
    long is not guarantee to be 32-bit
  • Khaled Mohamed
    Khaled Mohamed almost 6 years
    Actually 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
    ricco19 almost 6 years
    I believe long is required to be at least 32 bits? It's usually the same size as int though. Personally I always use fixed width integers if I require a specific capacity.
  • Chen Li
    Chen Li almost 6 years
    The language and its implementation are different things. So, you can say in most environments it will be 32-bit , but you can't say In C++ long is a 32-bit
  • ricco19
    ricco19 almost 6 years
    Is 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.