Creo que ambos están mal en C++17 1 y que el resultado esperado debería ser:
4294967295 0
Si bien el valor devuelto es correcto para las últimas versiones de ambos compiladores, creo que ios_base::failbit
debe establecerse, pero también creo que hay una confusión sobre la noción de campo a convertir en el estándar que puede dar cuenta de los comportamientos actuales.
El estándar dice:[facet.num.get.virtuals#3.3]:
Así que recurrimos a std::strtoull
, que debe devolver
2
ULLONG_MAX
y no establecer errno
en este caso (que es lo que hacen ambos compiladores).
Pero en el mismo bloque (énfasis es mía):
Tenga en cuenta que todas estas conversaciones sobre el "campo a convertir" y no el valor real devuelto por std::strtoull
. El campo aquí es en realidad la secuencia ampliada del carácter '-', '1'
.
Dado que el campo representa un valor (-1) que no se puede representar con un unsigned
, el valor devuelto debe ser UINT_MAX
y el bit de falla debe establecerse en std::cin
.
1
clang
en realidad tenía razón antes de C++17 porque la tercera viñeta en la cita anterior era:
2
std::strtoull
devuelve ULLONG_MAX
porque (gracias @NathanOliver) — C/7.22.1.4.5:
La pregunta es sobre las diferencias entre las implementaciones de la biblioteca libc++ y libstdc++, y no tanto sobre las diferencias entre los compiladores (clang, gcc).
cppreference aclara estas inconsistencias bastante bien:
Esto se resume a:
ULLONG_MAX
(4294967295
) es correcto en el futuro, ya que c++17 (ambos compiladores lo hacen correctamente ahora)- Anteriormente debería haber sido
0
con una lectura estricta del estándar (libc++) - Algunas implementaciones (notablemente libstdc++) siguieron
std::strtoull
protocolo en su lugar (que ahora se considera el comportamiento correcto)
El conjunto de bits de falla y por qué se configuró, podría ser una pregunta más interesante (al menos desde la perspectiva del abogado de idiomas). En la versión 7 de libc++ (clang) ahora hace lo mismo que libstdc++; esto parece sugerir que se eligió para ser igual que en el futuro (aunque esto va en contra de la letra del estándar, que debería ser cero antes de c++17 ), pero hasta ahora no he podido encontrar el registro de cambios o la documentación para este cambio.
El interesante bloque de texto dice (suponiendo que sea anterior a c++17):
De acuerdo con esto, el valor se especifica para ser 0
. Además, en ninguna parte se indica que esto deba resultar en la configuración del bit de error.