2009-08-11 22 views
7

Inicialmente pensé que necesitaba esto, pero finalmente lo evité. Sin embargo, mi curiosidad (y el apetito por el conocimiento, el zumbido) me hacen pregunto:Expansión de macro del preprocesador a otra directiva de preprocesador

Puede una macro de preprocesador, por ejemplo, en

#include "MyClass.h" 

INSTANTIATE_FOO_TEMPLATE_CLASS(MyClass) 

ampliar a otro incluyen, como en

#include "MyClass.h" 

#include "FooTemplate.h" 
template class FooTemplate<MyClass>; 

?

+2

Un día deseará transferir su código a un sistema operativo como Linux, donde el caso es significativo (es decir, Foo.h y foo.h son dos archivos diferentes) y luego todos los errores ortográficos que no se detectan en Windows llegarán a casa gallinero. alternativamente, si usted es una persona de Linux, un día querrá ir por el otro lado, con problemas diferentes pero igualmente horribles. –

+1

Estoy de acuerdo con la regla siempre en minúscula para los nombres de archivo. Lo escribí de esta manera porque quería excluir el problema de la conversión en minúsculas (nombre de clase -> nombre de archivo). Pero vale la pena mencionar, gracias. +1! – moala

+0

Nuestra regla es que los nombres de archivo coinciden exactamente con el esquema de nombres para nuestros tipos y funciones. Hacemos exactamente como el Interlocutor aquí, un nombre de tipo FooType se definirá en FooType.h. Al igual que con cualquier directriz de "estilo", elija un estilo y quédese con él. Una vez dicho esto, nos desarrollamos mucho en Linux, por lo que el sistema operativo nos impone automáticamente esta regla .... hmmmmm ..... –

Respuesta

12

Creo que no se puede hacer, esto es porque el preprocesador es single pass. Por lo tanto, no puede emitir otras directivas de preprocesador.

Específicamente, a partir de la Norma C99 (6.10.3.4 párrafo 3):

3 El resultante completamente -macro sustituye preprocesamiento contador secuencia no se procesa como una directiva preprocesamiento incluso si similar a uno ...

Es curioso que es por esto que el operador unary _Pragma se ha añadido a c99. Porque #pragma no pudo ser emitido por macros, pero _Pragma puede.

+0

Bueno, puede, por supuesto, emitir las directivas. lo que no puede hacer es procesarlos en el mismo pase de preprocesador. –

+1

Dado que los caracteres '#' y '##' tienen significados especiales en las macros, no veo cómo podría realmente emitir una directiva ... –

+0

En realidad, el preprocesador GCC parece permitir "#define X #ifdef X" donde el espacio entre el #ifdef y el segundo X es realmente una nueva línea, y esto realmente emite un #ifdef cuando ejecuta cpp en él. A alguien más le gustaría comprobar esto, ya que acabo de tomar un par de cervezas :-) –

9

El estándar C dice esto sobre preprocesamiento directivas (C99 - 6,10 (2) - directivas de preprocesamiento):

Una directiva de preprocesamiento consiste en una secuencia de tokens de preprocesamiento que comienza con un contador # preprocesamiento que (en el inicio de la fase de traducción 4) ...

y (C99 - 6.10 (7)):

Los tokens de preprocesamiento dentro de una directiva de preprocesamiento no están sujetos a la expansión macro a menos que se indique lo contrario.

Ejemplo En:

#define EMPTY 
EMPTY # include <file.h> 

la secuencia de fichas de pre-procesamiento en la segunda línea no es una directiva de preprocesamiento, ya que no comienza con un # al inicio de la fase de traducción 4, a pesar de que va a hacer entonces después de que el macro VACIO ha sido reemplazado

Entonces, no, las macros no pueden expandirse en una directiva de preprocesamiento '#include'. Esas directivas deben estar en su lugar al comienzo de la fase de traducción 4 (cuando se manejan esas directivas se produce el preprocesamiento). Dado que se produce la expansión de macros durante la fase 4, las macros no pueden hacer algo para existir al inicio de la fase 4.

me gustaría señalar sin embargo, que la siguiente hace trabajo:

#ifdef WIN32 
#define PLATFORM_HEADER "platform/windows/platform.h" 
#else 
#define PLATFORM_HEADER "platform/linux/platform.h" 

#include PLATFORM_HEADER 

porque el estándar C dice esto (C99, 6.10.2 (4) - Fuente de inclusión de archivo):

Una directiva de preprocesamiento de la forma

# include pp-tokens new-line 

(que no coincide con una de las dos formas anteriores) está permitido. Los tokens de preprocesamiento después de incluir en la directiva se procesan igual que en el texto normal. (Cada identificador actualmente se define como un nombre de macro es reemplazado por su lista de reemplazo de fichas de pre-procesamiento.)

+0

miré esa parte del estándar, pero no creo que sea la sección más relevante. El ejemplo no es uno que intente emitir una directiva. En cambio, es un ejemplo de una directiva que no está precedida por "espacios en blanco" (aunque la macro EMPTY se resuelve en espacios en blanco). –

+1

Estoy de acuerdo en que su cita del estándar es más directamente relevante, pero no estaba allí cuando contesté.Incluso si el ejemplo anterior no es el mismo de lo que se preguntó, el bit sobre la directiva de preprocesamiento que debe estar en el lugar al inicio de la fase 4 también impide que las macros se explayen en directivas de preprocesamiento útiles, incluso si 6.10.3.4 (3) lo dice más directamente. (En otras palabras, incluso si no creo que mi respuesta sea incorrecta, la suya es claramente una mejor respuesta). –

+0

Bastante, usted hace un buen punto, +1 :-). –

1

Todas las directivas del preprocesador se interpretan antes de la expansión de macro comienza, así que no, no se puede tener una macro se expanda en un # incluir directiva y hacer que se interprete como tal. En cambio, se interpretará como código C++ (erróneo).

+0

Puede obtener esta impresión porque muchas directivas deshabilitan la expansión de macro de sus argumentos, pero esto no es cierto. La expansión de macros ocurre al mismo tiempo que el análisis de directivas. Si fuera cierto, #if no funcionaría, y #undef no tendría el efecto que la gente espera. – zwol

Cuestiones relacionadas