c++ c++11 unicode utf-8 utf-16

Unicode en C++ 11



c++11 utf-8 (2)

He estado leyendo un poco sobre el tema de Unicode - específicamente, UTF-8 - (no) soporte en C ++ 11, y esperaba que los gurús de Stack Overflow pudieran asegurarme que mi comprensión es correcta , o señalar dónde he malentendido o perdido algo si ese es el caso.

Un breve resumen

Primero, lo bueno: puede definir literales UTF-8, UTF-16 y UCS-4 en su código fuente. Además, el encabezado <locale> contiene varias implementaciones std::codecvt que pueden convertir entre cualquiera de UTF-8, UTF-16, UCS-4 y la codificación multibyte de plataforma (aunque la API parece, por decirlo suavemente, menor que sencillo). Estas implementaciones de codecvt pueden ser codecvt imbue() ''d en las transmisiones para permitirle realizar conversiones a medida que lee o escribe un archivo (u otra transmisión).

[ EDIT: Cubbi señala en los comentarios que no mencioné el <codecvt> , que proporciona implementaciones std::codecvt que no dependen de una configuración regional. Además, las funciones std::wstring_convert y wbuffer_convert pueden usar estos codecvt para convertir cadenas y búferes directamente, sin depender de las transmisiones.]

C ++ 11 también incluye el encabezado C99 / C11 <uchar.h> que contiene funciones para convertir caracteres individuales de la codificación multibyte de la plataforma (que puede o no ser UTF-8) hacia y desde UCS-2 y UCS-4.

Sin embargo, eso es todo el alcance de eso. Si bien, por supuesto, puede almacenar texto UTF-8 en std::string , no hay formas en que pueda ver para hacer algo realmente útil con él. Por ejemplo, aparte de definir un literal en su código, no puede validar una matriz de bytes que contenga UTF-8 válido, no puede encontrar la longitud (es decir, el número de caracteres Unicode, para alguna definición de "carácter") ) de una std::string contiene UTF-8, y no puede iterar sobre std::string de ninguna otra forma que byte por byte.

De forma similar, incluso la adición de C ++ 11 de std::u16string realmente no es compatible con UTF-16, sino solo con UCS-2 anterior, no tiene soporte para pares de sustitución, dejándote solo con el BMP.

Observaciones

Dado que UTF-8 es la forma estándar de manejar Unicode en casi todos los sistemas derivados de Unix (incluidos Mac OS X y * Linux) y se ha convertido en el estándar de facto en la web, la falta de soporte en C ++ moderno parece como una omisión bastante grave. Incluso en Windows, el hecho de que la nueva std::u16string no sea realmente compatible con UTF-16 parece algo lamentable.

* Como se señala en los comentarios y se aclara here , las partes derivadas de BSD de Mac OS usan UTF-8 mientras que Cocoa usa UTF-16.

Preguntas

Si lograste leer todo eso, ¡gracias! Solo un par de preguntas rápidas, ya que esto es Stack Overflow después de todo ...

  • ¿Es correcto el análisis anterior o hay otras instalaciones de soporte de Unicode que me faltan?

  • El comité de estándares ha hecho un trabajo fantástico en los últimos años, avanzando C ++ a un ritmo rápido. Todos son personas inteligentes y asumo que son muy conscientes de las deficiencias anteriores. ¿Hay algún motivo particular bien conocido para que el soporte de Unicode siga siendo tan pobre en C ++?

  • En el futuro, ¿alguien sabe de alguna propuesta para rectificar la situación? Una búsqueda rápida en isocpp.org no pareció revelar nada.

EDITAR: Gracias a todos por sus respuestas. Tengo que confesar que los encuentro un poco desalentadores, parece que es improbable que el status quo cambie en el futuro cercano. Si hay un consenso entre los consultados, parece ser que el soporte completo de Unicode es demasiado difícil, y que cualquier solución debe volver a implementar la mayoría de las UCI para que se considere útil.

Yo personalmente no estoy de acuerdo con esto; Creo que hay un terreno intermedio valioso que se puede encontrar. Por ejemplo, los algoritmos de validación y normalización para UTF-8 y UTF-16 están bien especificados por el consorcio Unicode, y podrían ser suministrados por la biblioteca estándar como funciones gratuitas en, por ejemplo, un std::unicode nombres std::unicode . Solo estos serían una gran ayuda para los programas C ++ que necesitan interactuar con las bibliotecas que esperan entradas Unicode. Pero basado en la respuesta a continuación (matizada, debe decirse, con un toque de amargura) parece que la propuesta de Puppy para este tipo de funcionalidad limitada no fue bien recibida.


¿Es correcto el análisis anterior o hay otras instalaciones de soporte de Unicode que me faltan?

También te estás perdiendo la completa falla de los literales UTF-8. No tienen un tipo distinto de literales de caracteres angostos, que pueden tener una codificación totalmente no relacionada (por ejemplo, páginas de códigos). Así que no solo no agregaron ninguna nueva instalación seria en C ++ 11, rompieron lo poco que había porque ahora ni siquiera se puede asumir que un char* está en una codificación de cadena estrecha para su plataforma a menos que UTF-8 sea la codificación de cadena estrecha. Así que la nueva característica aquí es "Rompimos totalmente las cadenas basadas en char en todas las plataformas donde UTF-8 no es la codificación de cadena estrecha existente".

El comité de estándares ha hecho un trabajo fantástico en los últimos años, avanzando C ++ a un ritmo rápido. Todos son personas inteligentes y asumo que son muy conscientes de las deficiencias anteriores. ¿Hay algún motivo particular bien conocido para que el soporte de Unicode siga siendo tan pobre en C ++?

Al Comité simplemente no le importa una mierda sobre Unicode.

Además, muchos de los algoritmos de soporte Unicode son solo eso: algoritmos. Esto significa que para ofrecer una interfaz decente, necesitamos rangos. Y todos sabemos que el Comité no puede descifrar qué quieren los rangos de wrt. La nueva cosa de Iterables de Eric Niebler puede tener una oportunidad.

En el futuro, ¿alguien sabe de alguna propuesta para rectificar la situación? Una búsqueda rápida en isocpp.org no pareció revelar nada.

Había N3572, del cual fui autor. Pero cuando fui a Bristol y lo presenté, hubo una serie de problemas.

En primer lugar, resulta que el Comité no se molesta en retroalimentar las propuestas no creadas por miembros del Comité entre las reuniones, lo que genera meses de trabajo perdido cuando itera sobre un diseño que no desea.

En segundo lugar, resulta que es votado por quien se pasea en ese momento. Esto significa que si su periódico es reprogramado, tiene un grupo relativamente aleatorio de personas que pueden o no saber algo sobre el tema. O de hecho, cualquier cosa.

En tercer lugar, por alguna razón, no parecen ver la situación actual como un problema grave. Puede obtener una discusión interminable sobre cómo exactamente deben definirse las operaciones de comparación de optional<T> , pero ¿ cómo lidiar con las aportaciones del usuario ? A quién le importa eso?

En cuarto lugar, cada documento necesita un campeón, efectivamente, para presentarlo y mantenerlo. Teniendo en cuenta los problemas anteriores, más el hecho de que no hay manera de que yo pueda pagar para viajar a otras reuniones, ciertamente no iba a ser yo, no seré yo en el futuro a menos que desee donar todos mis gastos de viaje y pagar un salario en la parte superior, y nadie parecía preocuparse lo suficiente como para esforzarse.


Es el análisis anterior correcto

Veamos.

no puede validar una matriz de bytes que contenga UTF-8 válido

Incorrecto. std::codecvt_utf8<char32_t>::length(start, end, max_lenght) devuelve la cantidad de bytes válidos en la matriz.

no puedes averiguar la longitud

Parcialmente correcto. Uno puede convertir a char32_t y averiguar la duración del resultado. No hay una manera fácil de conocer la longitud sin realizar la conversión real (pero consulte a continuación). Debo decir que la necesidad de contar personajes (en cualquier sentido) surge con bastante poca frecuencia.

no puede iterar sobre una cadena std :: de ninguna otra forma que byte a byte

Incorrecto. std::codecvt_utf8<char32_t>::length(start, end, 1) le da la posibilidad de iterar sobre "caracteres" UTF-8 (unidades de código Unicode), y por supuesto determinar su número (esa no es una manera "fácil") contar el número de caracteres, pero es una manera).

realmente no es compatible con UTF-16

Incorrecto. Se puede convertir std::codecvt_utf8_utf16<char16_t> desde UTF-16 con, por ejemplo, std::codecvt_utf8_utf16<char16_t> . Un resultado de la conversión a UTF-16 es, bueno, UTF-16. No está restringido a BMP.

Demostración que ilustra estos puntos .

Si me perdí algún otro "no puedes", indícalo y lo abordaré.

Adenda importante Estas instalaciones están en desuso en C ++ 17. Esto probablemente significa que desaparecerán en alguna versión futura de C ++. Usélos bajo su propio riesgo. Todas estas cosas enumeradas en la pregunta original ahora no se pueden (de manera segura) volver a hacer, usando solo la biblioteca estándar.