2010-11-26 22 views
13

Mi modelo mental de cómo funciona el preprocesador es aparentemente incompleto, y esto me está volviendo loco.Preprocessor token expansion

Quiero concatenar dos tokens, pero el segundo token debe expandirse primero.

#define ANSWER 42 

#define FOO foo_ ## ANSWER 

Aquí, FOO se expande a foo_ANSWER, pero quiero que sea foo_42. Por lo tanto, definir una macro MERGE con la esperanza de que esto de alguna manera expandir los argumentos antes de la concatenación:

#define MERGE(x, y) x ## y 

#define BAR MERGE(bar_, ANSWER) 

Pero BAR todavía se expande a bar_ANSWER en lugar de bar_42. Así defino otra macro HELPER:

#define HELPER(x, y) MERGE(x, y) 

#define BAZ HELPER(baz_, ANSWER) 

Y ahora BAZ se expande con éxito a baz_42. Por el momento, esto me parece mágico.

¿Alguien me puede explicar este comportamiento? ¿Cómo funcionan las reglas de expansión exactamente?

+0

lo siento decir que también me hice una pregunta posible duplicado de esta misma edición. Me pregunto por qué este comportamiento no está documentado claramente. Me refiero al algoritmo que opera el preprocesador. –

+0

@sandundhammika: Está bastante claramente documentado en la especificación - sección 6.10.3 - aunque hay una serie de esquinas de comportamiento no definidas. –

Respuesta

7

Leer la respuesta a su pregunta here:

El problema es que cuando se tiene un reemplazo macro , el preprocesador única ampliará las macros forma recursiva si ni el stringizing operador # ni el token -pasting operador ## se le aplican. Por lo tanto, tiene que utilizar algunas capas extra de indirección , puede utilizar el operador de red en pegar con un argumento recursiva ampliado

+0

Y esta es la razón por la cual hay 'BOOST_PP_CAT' :) –

+0

La cita anterior no es correcta, o al menos no está completa. Para expandir la macro, necesita DOS niveles de direccionamiento indirecto (probado en VS2017 e informes de lo mismo en Gnu cpp). Me gustaría escuchar una explicación de por qué es necesario el segundo nivel de indirección. Tener solo un nivel de indirección, sin ningún "#" o "##", no expande la macro. Pero el 2do nivel sí. –

3

concatenación de emergencia no se expande macros cuando se realiza la concatenación [ref].

Para superar esto, utiliza un nivel de direccionamiento indirecto y obtiene el preprocesador para expandir las macros antes de la concatenación.

#define STEP1(x, y) STEP2(x, y) // x and y will be expanded before the call to STEP2 
#define STEP2(x, y) x ## y   // x and y will not be expanded, just pasted