Czy to błąd w std :: gcd?

14

Natknąłem się na takie zachowanie, std::gcdktóre okazało się nieoczekiwane:

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

Uruchom w eksploratorze kompilatorów

Zgodnie z preferencją obu wywołań std::gcdnależy się poddać 10, ponieważ wszystkie warunki wstępne są spełnione.

W szczególności wymagane jest jedynie, aby wartości bezwzględne obu operandów były reprezentowalne we wspólnym typie:

Jeśli albo | m | lub | n | nie jest reprezentowalna jako wartość typu std::common_type_t<M, N>, zachowanie jest niezdefiniowane.

Jednak pierwsze połączenie powraca 2. Czy coś mi umyka? Zarówno gcc, jak i clang zachowują się w ten sposób.

Dave
źródło
co ciekawe, gcc kompiluje 2 inty po prostu wypisując wartość, ale int i niepodpisane nie: godbolt.org/z/koEVHh
Alan Birtles
Co jest -120 % 10u? (Wskazówka: nie jest to 0.) Tak, błąd.
TC
@TC Tak, casting -120do unsignedspowoduje 4294967176który % 10ujest 6. Moje pytanie dotyczyło raczej tego, czy takie zachowanie jest rzeczywiście nieprawidłowe, a wydaje się, że tak.
dave
@AlanBirtles W takim przypadku nie zostanie wysłany unsigned, więc też nie będzie żadnego błędu
dave

Odpowiedzi:

10

Wygląda jak błąd w libstc ++. Jeśli dodasz -stdlib=libc++do wiersza polecenia CE, otrzymasz:

-120 120
10 10
10
10
Marshall Clow
źródło