C++ 20 con u8, char8_t y std:: string
stdstring c++20 (2)
C ++ 11 nos trajo el prefijo u8 para los literales UTF-8 y pensé que era muy bueno hace unos años y salpicé mi código con cosas como esta:
std::string myString = u8"●";
Todo esto está muy bien, pero el problema aparece en C ++ 20, parece que ya no se compila porque u8 crea un char8_t * y esto es incompatible con std :: string que solo usa char.
¿Debo estar creando una nueva utf8string? ¿Cuál es la manera correcta y coherente de hacer este tipo de cosas en un mundo de C ++ 20 donde tenemos tipos más explícitos que no coinciden realmente con la cadena estándar std ::?
¿Debo estar creando una nueva utf8string?
No, ya está ahí.
P0482
no solo propone
char8_t
, sino también una nueva especialización de
std::basic_string
para los tipos de caracteres
char8_t
denominados
std::u8string
.
Así que esto ya compila con
clang
y
libc++
desde el tronco:
const std::u8string str = u8"●";
El hecho de que la construcción de
std::string
de
u8
-literal se rompa es desafortunado.
De la propuesta:
Esta propuesta no especifica ninguna característica de compatibilidad con versiones anteriores que no sea la de retener las interfaces que deja en desuso. La falta de tales características no se debe a la creencia de que las características de compatibilidad con versiones anteriores no son necesarias. El autor cree que tales características son necesarias, pero las limitaciones de tiempo impidieron investigar adecuadamente qué problemas deben abordarse, en qué medida deben abordarse y cómo deben especificarse esas características. [...]
Pero supongo que la mayor parte de la inicialización como la anterior debería ser
grep
-able o estar sujeta a algunas correcciones de herramientas de sonido automático.
Además de la respuesta de @lubgr, la
corrección de compatibilidad con versiones anteriores
del artículo
char8_t (P1423)
describe varias formas de hacer
std::string
con matrices de caracteres
char8_t
.
Básicamente, la idea es que puede convertir la matriz de caracteres
u8
en una matriz de caracteres "normal" para obtener el mismo comportamiento que C ++ 17 y antes, solo tiene que ser un poco más explícito.
El documento discute varias maneras de hacer esto.
El método más simple (pero no totalmente nulo, a menos que agregue más sobrecargas) que se ajuste a su caso de uso es probablemente el último, es decir, introduzca funciones de conversión explícitas:
std::string from_u8string(const std::string &s) {
return s;
}
std::string from_u8string(std::string &&s) {
return std::move(s);
}
#if defined(__cpp_lib_char8_t)
std::string from_u8string(const std::u8string &s) {
return std::string(s.begin(), s.end());
}
#endif