Codificación Unicode para literales de cadena en C ++ 11

Después de una pregunta relacionada , me gustaría preguntar sobre el nuevo carácter y los tipos de cadenas literales en C ++ 11. Parece que ahora tenemos cuatro tipos de caracteres y cinco tipos de literales de cadenas. Los tipos de personajes:

char a = '\x30'; // character, no semantics wchar_t b = L'\xFFEF'; // wide character, no semantics char16_t c = u'\u00F6'; // 16-bit, assumed UTF16? char32_t d = U'\U0010FFFF'; // 32-bit, assumed UCS-4 

Y los literales de cadena:

 char A[] = "Hello\x0A"; // byte string, "narrow encoding" wchar_t B[] = L"Hell\xF6\x0A"; // wide string, impl-def'd encoding char16_t C[] = u"Hell\u00F6"; // (1) char32_t D[] = U"Hell\U000000F6\U0010FFFF"; // (2) auto E[] = u8"\u00F6\U0010FFFF"; // (3) 

La pregunta es esta: ¿Las referencias de caracteres \x / \u / \U libremente combinables con todos los tipos de cadenas? ¿Son todos los tipos de cadenas de ancho fijo, es decir, las matrices contienen precisamente tantos elementos como aparecen en el literal, o las referencias a \x / \u / \U se expanden en un número variable de bytes? ¿ u8"" cadenas tienen semántica de encoding, por ejemplo, puedo decir char16_t x[] = u"\U0010FFFF" , y el punto de código que no es BMP se codifica en una secuencia UTF16 de dos unidades? Y de manera similar para u8 ? En (1), ¿puedo escribir sustitutos solitarios con \u ? Finalmente, ¿alguna de las funciones de la cadena de encoding es consciente (es decir, tienen en cuenta los caracteres y pueden detectar secuencias de bytes no válidas)?

Esta es una pregunta un tanto abierta, pero me gustaría obtener una imagen lo más completa posible de las nuevas funciones de encoding y tipo UTF del nuevo C ++ 11.

¿Las referencias de caracteres \ x / \ u / \ U son libremente combinables con todos los tipos de cadenas?

No. \x se puede usar en cualquier cosa, pero \u \U solo se pueden usar en cadenas que están específicamente codificadas en UTF. Sin embargo, para cualquier cadena codificada en UTF, \u y \U pueden usarse como mejor le parezca.

¿Son todos los tipos de cadenas de ancho fijo, es decir, las matrices contienen precisamente tantos elementos como aparecen en el literal, o las referencias a \ x / \ u / \ U se expanden en un número variable de bytes?

No de la manera que quieres decir. \x , \u , y \U se convierten en función de la encoding de cadena. El número de esas “unidades de código” (usando términos Unicode. Un char16_t es una unidad de código UTF-16) depende de la encoding de la cadena que contiene. El literal u8"\u1024" crearía una cadena que contiene 2 caracteres más un terminador nulo. El literal u"\u1024" crearía una cadena que contiene 1 char16_t más un terminador nulo.

La cantidad de unidades de código utilizadas se basa en la encoding Unicode.

¿Sus cadenas tienen semántica de encoding, por ejemplo, puedo decir char16_t x [] = u “\ U0010FFFF”, y el punto de código que no es BMP se codifica en una secuencia UTF16 de dos unidades?

u"" crea una cadena codificada en UTF-16. u8"" crea una cadena codificada en UTF-8. Se codificarán según la especificación Unicode.

En (1), ¿puedo escribir sustitutos solitarios con \ u?

Absolutamente no. La especificación prohíbe expresamente utilizar los pares de sustitución UTF-16 (0xD800-0xDFFF) como puntos de código para \u o \U

Finalmente, ¿alguna de las funciones de la cadena de encoding es consciente (es decir, tienen en cuenta los caracteres y pueden detectar secuencias de bytes no válidas)?

Absolutamente no. Bueno, permíteme reformular eso.

std::basic_string no se ocupa de las codificaciones Unicode. Ciertamente pueden almacenar cadenas codificadas en UTF. Pero solo pueden pensar en ellos como secuencias de char , char16_t o char32_t ; no pueden pensar en ellos como una secuencia de puntos de código Unicode que están codificados con un mecanismo particular. basic_string::length() devolverá el número de unidades de código, no puntos de código. Y, obviamente, las funciones de cadena de la biblioteca estándar C son totalmente inútiles

Sin embargo, debe tenerse en cuenta que “longitud” para una cadena Unicode no significa la cantidad de puntos de código. Algunos puntos de código combinan “caracteres” (un nombre desafortunado), que se combinan con el punto de código anterior. Por lo tanto, múltiples puntos de código se pueden asignar a un único carácter visual.

De hecho, Iostreams puede leer / escribir valores codificados en Unicode. Para hacerlo, deberá usar una configuración regional para especificar la encoding e insertarla correctamente en los distintos lugares. Esto es más fácil decirlo que hacerlo, y no tengo ningún código sobre mí para mostrarte cómo.