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.
-120 % 10u? (Wskazówka: nie jest to 0.) Tak, błąd.
-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.
unsigned, więc też nie będzie żadnego błędu