Це помилка в std :: gcd?


14

Я натрапив на таку поведінку, std::gcdщо мені виявилося несподіваним:

#include <iostream>
#include <numeric>

int main()
{
    int      a = -120;
    unsigned b =  10;

    //both a and b are representable in type C
    using C = std::common_type<decltype(a), decltype(b)>::type;
    C ca = std::abs(a);
    C cb = b;
    std::cout << a << ' ' << ca << '\n';
    std::cout << b << ' ' << cb << '\n';

    //first one should equal second one, but doesn't
    std::cout << std::gcd(a, b) << std::endl;
    std::cout << std::gcd(std::abs(a), b) << std::endl;
}

Запустити на компілятор Explorer

Відповідно до cppreference, обидва заклики до цього std::gcdповинні мати результат 10, оскільки всі передумови виконуються.

Зокрема, потрібно лише, щоб абсолютні значення обох операндів були представлені в їх загальному типі:

Якщо або | м | або | n | не є репрезентабельним як значення типу std::common_type_t<M, N>, поведінка не визначена.

І все ж перший дзвінок повертається 2. Я щось тут пропускаю? І gcc, і clang так поводяться.


Цікаво, що gcc збирає 2 int, щоб просто надрукувати значення, але int і не підписане: godbolt.org/z/koEVHh
Alan

Що -120 % 10u? (Підказка: це не 0.) Так, помилка.
ТК

@TC Так, кастинг -120для unsignedцього призведе до того, 4294967176що % 10uє 6. Моє запитання було скоріше, чи така поведінка справді неправильна, що, здається, є.
Дейв

@AlanBirtles У такому випадку тер не буде відзначений unsigned, тому жодна помилка не буде
Дейв

1
Повідомлено як gcc.gnu.org/bugzilla/show_bug.cgi?id=92978
ТК

Відповіді:


10

Схоже на помилку в libstc ++. Якщо ви додасте -stdlib=libc++до командного рядка CE, ви отримаєте:

-120 120
10 10
10
10
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.