Ошибка g ++: вызов перегруженного 'abs (unsigned int)' неоднозначен - PullRequest
0 голосов
/ 12 мая 2018

Я пытаюсь скомпилировать следующий код:

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

с использованием g++ test.cc -o test.

Однако компилятор g ++ завершается ошибкой со следующей ошибкой:

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); }                                                
   ^~~     

Почему эта ошибка происходит и как ее исправить?

g ++ версия: gcc версия 6.3.0

Ответы [ 3 ]

0 голосов
/ 12 мая 2018

Вы можете просто привести результат к подписанному типу данных, чтобы пресс знал, к какому типу вы звоните, как это:

while( abs( int(res1 - res2) ) > 1 )

но еще раз подумайте о том, что вам нужно сделать здесь, так как результат операции минус на unsigned все еще не подписан, поэтому, если результат опустится ниже 0, он превратится в большое число (как нормальное переполнение), поэтому я думаю, использование подписанных переменных - лучший способ решить проблему в первую очередь

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;
}
0 голосов
/ 12 мая 2018

abs в <stdlib.h> (начиная с 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);

Вызов будет неоднозначным , если перегрузка разрешение не может выбрать совпадение с вызовом, которое однозначно лучше, чем такие недифференцируемые функции.

Вы можете привести аргумент в явном виде, например:

static_cast<int>(res1 - res2)
0 голосов
/ 12 мая 2018

Редактировать: <cstdlib> должен обрабатывать перегрузки (и в любом случае должен быть предпочтительным), см. Вопрос здесь

Обратите внимание, что здесь есть некоторые логические ошибки.Прежде всего, то, что вы делаете, вероятно, не то, что вы хотите.res1 - res2 является арифметикой между двумя unsigned типами, и поэтому результат также будет unsigned.Если вы опуститесь ниже 0, вы вернетесь к макс.abs() здесь бессмысленно, это значение никогда не будет отрицательным , потому что тип запрещает его.Даже с заголовком, который компилирует этот код, компилятор все равно предупредит об этом.

Я настоятельно рекомендую вам придерживаться целых чисел со знаком при работе с арифметикой, чтобы избежать этих ловушек, и если вы действительно нужно хранилище, используйте 64-битные целые числа.

Таким образом, мой реальный ответ был бы: переключите unsigned на int

Также обратите внимание: unsigned res2 = i / res1; res2 будет усечено до 0 здесьЯ не уверен, хотите ли вы этого или нет.

...