BookinglyTech News
Software

C++20 rompe la compatibilidad de los literales u8: ahora son char8_t

C++20 cambió el tipo de los literales u8 de const char a const char8_t. El código que compilaba en C++17 deja de hacerlo, MSVC lo rechaza y Google recomienda evitar el prefijo.

2 min de lecturaLobsters0 vistas

Un literal u8 en C++ no siempre significó lo mismo. Hasta C++20, una cadena con ese prefijo se interpretaba como un array de const char. A partir de C++20, ese mismo literal pasa a ser un array de const char8_t. El cambio es deliberado y rompe compatibilidad: código que compilaba en C++17 deja de compilar al subir a C++20.

El ejemplo mínimo es una función que recibe un const char* y una llamada con un literal u8. En C++17, auto s = u8"Connie plus some UTF-8 stuff..."; produce algo que encaja con DoSomething(s). En C++20, s es const char8_t*, y MSVC responde que no puede convertir el argumento 1 de const char8_t* a const char*. El compilador no está siendo caprichoso: son tipos distintos y la sobrecarga ya no encuentra la función que esperabas.

Qué cambia exactamente

La tabla es corta. Antes de C++20, un literal u8 era const char[N] con codificación UTF-8. Desde C++20, es const char8_t[N], también UTF-8, pero con un tipo distinto. Ese char8_t se introdujo para separar el texto UTF-8 de los bytes de carácter ordinario. La intención era buena; el efecto secundario es que cualquier API, plantilla o biblioteca que espere const char* o std::string deja de aceptar esos literales sin una conversión.

En un fragmento de juguete se arregla rápido. En una base de código grande, con bibliotecas de terceros y código heredado que llevaba años compilando en C++17, el cambio aparece de golpe al activar C++20. No es una advertencia: es un error de compilación. Y no afecta solo a una función suelta, sino a todas las rutas donde un literal u8 acabe en una interfaz que espere char.

Qué recomienda la guía de Google

La guía de estilo de C++ de Google recomienda evitar el prefijo u8 cuando se pueda. El motivo es que tiene semántica muy distinta desde C++20 respecto a C++17, produce arrays de char8_t en lugar de char, y volverá a cambiar en C++23. Para código nuevo, esa recomendación elimina el problema de raíz. Para código existente, la decisión es menos cómoda: tocar las firmas para aceptar char8_t, convertir en los puntos de entrada o dejar de usar el prefijo.

El detalle a retener es que la compatibilidad hacia atrás en C++ es una tendencia, no una garantía. Si tienes una base de código que aún compila en C++17 y planeas saltar a C++20, los literales u8 son uno de los puntos donde el salto se nota. Revisa cuántos hay, en qué APIs terminan y si esas APIs son tuyas o de una dependencia. Ahí está el trabajo real.