Apakah ini bug di std :: gcd?

14

Saya menemukan perilaku std::gcdyang tidak terduga ini:

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

Jalankan pada compiler explorer

Menurut cppreference, kedua panggilan std::gcdharus menghasilkan 10, karena semua prasyarat dipenuhi.

Secara khusus, hanya diperlukan bahwa nilai absolut dari kedua operan diwakili dalam tipe umum mereka:

Jika salah | m | atau | n | tidak dapat direpresentasikan sebagai nilai tipe std::common_type_t<M, N>, perilaku tidak terdefinisi.

Namun panggilan pertama kembali 2. Apakah saya melewatkan sesuatu di sini? Baik gcc dan dentang berperilaku seperti ini.

dave
sumber
menariknya gcc mengkompilasi 2 int untuk mencetak nilai tetapi int dan unsigned tidak: godbolt.org/z/koEVHh
Alan Birtles
Apa -120 % 10u? (Petunjuk: ini bukan 0.) Ya, bug.
TC
@TC Ya, casting -120untuk unsignedakan menghasilkan 4294967176yang % 10umerupakan 6. Pertanyaan saya adalah lebih tepatnya apakah perilaku ini memang salah, yang sepertinya.
dave
@AlanBirtles Dalam hal ini, tidak akan ada pemain unsigned, jadi tidak ada bug juga
dave

Jawaban:

10

Sepertinya ada bug di libstc ++. Jika Anda menambahkan -stdlib=libc++ke baris perintah CE, Anda akan mendapatkan:

-120 120
10 10
10
10
Marshall Clow
sumber