2011-07-28 15 views
9

Es bastante común utilizar la concatenación de macros y tokens para alternar entre cadenas anchas y angostas en tiempo de compilación.¿Se revierten las sustituciones de trigrafos cuando se crea una cadena sin formato mediante concatenación?

#define _T(x) L##x 
const wchar_t *wide1 = _T("hello"); 
const wchar_t *wide2 = L"hello"; 

Y en C++ 11 debería ser válido para confeccionar una cosa similar con cadenas primas:

#define RAW(x) R##x 
const char *raw1 = RAW("(Hello)"); 
const char *raw2 = R"(Hello)"; 

Desde expansión de la macro y la concatenación de contadores ocurre antes de la sustitución de secuencia de escape, esto debería evitar secuencias de escape siendo reemplazado en la cadena citada.

Pero, ¿cómo se aplica esto a los trigrafos? ¿Las cadenas sin formato formadas mediante concatenación con cadenas normales aún están sujetas a que se reviertan sus sustituciones de trigrafos?

const char *trigraph = RAW("(??=)");  // Is this "#" or "??="? 
+2

¿Cuánto tiempo lleva probar esto en un compilador, frente al tiempo dedicado a hacer la pregunta aquí? –

+5

No estoy buscando usarlo en el código de producción, estoy escribiendo un compilador y parece un caso extremo. Además, no conozco ningún compilador con soporte completo de C++ 0x (y no creo que el estándar final haya sido publicado aún). –

+7

@Damien esa no es una respuesta adecuada ... Los compiladores para C++ saben divergir de la especificación –

Respuesta

6

No, el trigraph no se revierte en su ejemplo.

[lex.phases]p1 identifica tres fases de traducción relevantes a su pregunta:

1. Secuencias trigraph se sustituyen por los correspondientes representaciones internas de un solo carácter.
3. El archivo de origen se descompone en tokens de preprocesamiento.
4. Las invocaciones de macros se expanden.

La fase 1 está definida por [lex.trigraph]p1. En esta etapa, su código se traduce al const char *trigraph = RAW("(#)").

La fase 3 está definida por [lex.pptoken]. Esta es la etapa en la que los trigrafos se revierten en literales de cadena sin formato. El párrafo 3 dice:

Si el siguiente carácter se inicia una secuencia de caracteres que podrían ser el pre fi jo y comillas dobles inicial de una cadena de texto literal, tal como R", el siguiente token de procesamiento previo deberá ser una cadena de texto literal. entre los caracteres de comillas dobles inicial y final de la cuerda en bruto, las transformaciones realizadas en las fases 1 y 2 (trigrafos, universal caracteres nombres y empalme de línea) se revierten.

Ese no es el caso en su ejemplo, por lo tanto, el trigraph no se revierte.Su código se transforma en la secuencia preprocesamiento-tokenconstchar*trigraph=RAW("(#)")

Finalmente, en la fase 4, el RAW macro se expande y el token-pasta se produce, lo que resulta en la siguiente secuencia de preprocesamiento-tokens: constchar*trigraph=R"(#)". El r-char-sequence del literal de cadena comprende un #. La fase 3 ya se ha producido y no hay otro punto en el que se produzca la reversión de los trigrafos.

0

La sustitución del trígono ocurre antes del macroprocesamiento.

UPD No tenga en cuenta esto. No me he dado cuenta de que C++ 0x revierte los trigrafos en literales de cadenas sin formato.

UPD2 2.5.3 describe el proceso de formación de tokens de preprocesamiento literal de cadena sin procesar. La inversión de Trigraph es parte de este proceso. No hay literales de cadena sin procesar que no sean tokens de preprocesamiento. Entonces, la respuesta a su pregunta parece ser sí.

+1

Entiendo que la sustitución ocurre antes del macroprocesamiento, pero el estándar se refiere a las sustituciones de trigrafos siendo/revertidas/para literales de cadenas sin formato. Debido a que el literal de cadena cruda solo se forma más tarde (como resultado de la concatenación), tengo curiosidad sobre si ese sigue siendo el caso. –

Cuestiones relacionadas