2008-11-05 14 views
25

¿Existe alguna manera de definir una macro que pueda contener la directiva #include en su cuerpo?definición de macro que contiene la directiva #include

Si acabo de poner la "#include", da error

C2162: "expected macro formal 

parámetro"

ya que aquí no estoy utilizando # para concatenar cadenas.
Si uso "\# include", entonces recibo los dos errores siguientes:

error C2017: illegal escape sequence 
error C2121: '#' : invalid character : possibly the result of a macro expansion 

¿Alguna ayuda?

Respuesta

1

¿Por qué la macro necesita tener un #include? si # incluye el archivo en el que se encuentra la macro, puede poner el #include encima de la macro con el resto de las instrucciones #include, y todo debe ser agradable y elegante.

No veo ninguna razón para que la macro incluya algo que simplemente no podría incluirse en el archivo.

5

Creo que el preprocesador C/C++ solo hace una sola pasada sobre el código, así que no creo que eso funcione. Es posible que pueda obtener un "#include" para que la macro lo coloque en el código, pero el compilador se ahogaría, ya que no sabe qué hacer con eso. Para lo que intenta hacer para trabajar, el preprocesador tendría que hacer una segunda pasada sobre el archivo para recoger el #include.

-7

contagiosa que es correcto - si está haciendo:

myFile.c:

#include "standardAppDefs.h" 
#myStandardIncludeMacro 

standardAppDefs.h:

#define myStandardIncludeMacro #include <foo.h> 

¿Por qué no dicen:

myFile.c:

#include "standardAppDefs.h" 

standardAppDefs.h:

#include <foo.h> 

y olvidar las macros?

3

creo que estás bien en que esta tarea parece imposible que yo también recibí de

http://groups.google.com/group/comp.lang.c++/browse_thread/thread/03d20d234539a85c#

No, las directivas de preprocesador en C++ (y C) no son un reflejo.

Pawel Dziepak

De todos modos, la razón detrás de este intento es que yo estoy tratando de hacer lo siguiente usado repetidamente fragmento de código como una macro:

void foo(AbstractClass object) 
{ 
    switch (object.data_type()) 
    { 
    case AbstractClass::TYPE_UCHAR : 
     { 
     typedef unsigned char PixelType; 
     #include "snippets/foo.cpp" 
     } 
     break; 
    case AbstractClass::TYPE_UINT: 
     { 
     typedef unsigned int PixelType; 
     #include "snippets/foo.cpp" 
     } 
     break; 
    default: 
     break; 
    } 
} 

Por otra tarea, necesito tener una función similar

void bar(AbstractClass object) 

donde voy a colocar

#include "snippets/bar.cpp" 

y, por supuesto, está escrito en "snippets/foo.cpp" y "snippets/bar.cpp" el código específico de la tarea.

+2

Probablemente deberías mirar las plantillas (como stbuton sugirió). Ciertamente deberías estar buscando evitar tener que hacer eso. –

+0

como regla general, probablemente debas colocar todos tus enunciados #include en el mismo lugar (normalmente en la parte superior). hace que mantener y depurar su código sea mucho más simple. – helloandre

+0

Tengo una forma un poco loca de hacer básicamente lo que quiere (usando el preprocesador); ver mi respuesta :) http://stackoverflow.com/a/27830271/1447953 –

9

No voy a discutir los méritos para ello, pero freetype (www.freetype.org) realiza lo siguiente:

#include FT_FREETYPE_H 

donde se definen FT_FREETYPE_H otra parte

+8

Esto está explícitamente permitido en los estándares, y por lo tanto es portátil siempre que FT_FREETYPE_H se expanda al formulario o al "encabezado.h". –

+0

+1, ya que esto evita depender del comportamiento definido por la implementación, incluso si no significa confiar mucho en su sistema de compilación. – einpoklum

0

que no tienen idea de lo que son en realidad tratando de hacer, pero parece que lo que puede querer es una función de plantilla.

De esta forma, PixelType es solo un parámetro de plantilla para el bloque de código.

4

También quería hacer esto, y aquí está la razón:

Algunos archivos de cabecera (en particular en mpi.h OpenMPI) funcionan de forma diferente si está compilando en C o C++. Me estoy vinculando a un código C MPI de mi programa C++. Para incluir la cabecera, hago lo habitual:

extern "C" { 
#include "blah.h" 
} 

Pero esto no funciona porque __cplusplus todavía está definido aún en C vinculación. Eso significa que mpi.h, que está incluido en blah.h, comienza a definir las plantillas y el compilador muere diciendo que no puede usar plantillas con vinculación C.

Por lo tanto, lo que tengo que hacer en blah.h es reemplazar

#include <mpi.h> 

con

#ifdef __cplusplus 
#undef __cplusplus 
#include <mpi.h> 
#define __cplusplus 
#else 
#include <mpi.h> 
#endif 

Cabe destacar que no se trata sólo mpi.h que hace esta cosa patológica. Por lo tanto, quiero definir una macro INCLUDE_AS_C que hace lo anterior para el archivo especificado. Pero supongo que eso no funciona.

Si alguien puede encontrar otra forma de lograr esto, hágamelo saber.

+0

Las pseudo-macros que describo en mi respuesta te dejarían hacer esto :). La sintaxis no es tan buena como lo sería una macro normal, pero funcionaría :). Usted terminaría con algo como "#define FILENAME ", "#include include_as_c.hpp", "#undef FILENAME", con su forma especial de incluir dentro include_as_c.hpp. http://stackoverflow.com/questions/266501/macro-definition-containing-include-directive/27830271#27830271 –

6

Los lenguajes C y C++ prohíben explícitamente formar directivas de preprocesador como resultado de la macro expansión. Esto significa que no puede incluir una directiva de preprocesador en una lista de reemplazo de macro. Y si intenta engañar al preprocesador "construyendo" una nueva directiva de preprocesador a través de la concatenación (y trucos como ese), el comportamiento no está definido.

14

Así como los demás dicen, no, no puede tener declaraciones #include dentro de una macro, ya que el preprocesador solo hace una pasada. Sin embargo, puedes hacer que el preprocesador haga básicamente lo mismo con un truco retorcido que me encontré usando recientemente.

Tenga en cuenta que las directivas de preprocesador no harán nada dentro de una macro, sin embargo, HARÁN algo en un archivo. Por lo tanto, puede pegar un bloque de código que desea mutar en un archivo, pensando en ello como una definición de macro (con piezas que pueden ser alteradas por otras macros), y luego # incluir este archivo pseudo-macro en varios lugares (hacer ¡seguro que no tiene guardias incluidas!). No se comporta exactamente como lo haría una macro, pero puede lograr algunos resultados bastante similares a los macros, ya que #include básicamente solo descarga los contenidos de un archivo a otro.

Por ejemplo, considere incluir muchos encabezados de nombre similar que vienen en grupos. Es tedioso escribirlos todos, o tal vez incluso se generan automáticamente. Puede automatizar parcialmente su inclusión al hacer algo como esto:

ayudante macros de cabecera:

/* tools.hpp */ 

#ifndef __TOOLS_HPP__ 
#def __TOOLS_HPP__ 

// Macro for adding quotes 
#define STRINGIFY(X) STRINGIFY2(X)  
#define STRINGIFY2(X) #X 

// Macros for concatenating tokens 
#define CAT(X,Y) CAT2(X,Y) 
#define CAT2(X,Y) X##Y 
#define CAT_2 CAT 
#define CAT_3(X,Y,Z) CAT(X,CAT(Y,Z)) 
#define CAT_4(A,X,Y,Z) CAT(A,CAT_3(X,Y,Z)) 
// etc... 

#endif 

archivo Pseudo-macro

/* pseudomacro.hpp */ 

#include "tools.hpp" 
// NO INCLUDE GUARD ON PURPOSE 
// Note especially FOO, which we can #define before #include-ing this file, 
// in order to alter which files it will in turn #include. 
// FOO fulfils the role of "parameter" in this pseudo-macro. 

#define INCLUDE_FILE(HEAD,TAIL) STRINGIFY(CAT_3(HEAD,FOO,TAIL)) 

#include INCLUDE_FILE(head1,tail1.hpp) // expands to #head1FOOtail1.hpp 
#include INCLUDE_FILE(head2,tail2.hpp) 
#include INCLUDE_FILE(head3,tail3.hpp) 
#include INCLUDE_FILE(head4,tail4.hpp) 
// etc.. 

#undef INCLUDE_FILE 

archivo Fuente

/* mainfile.cpp */ 

// Here we automate the including of groups of similarly named files 

#define FOO _groupA_ 
#include "pseudomacro.hpp" 
// "expands" to: 
// #include "head1_groupA_tail1.hpp" 
// #include "head2_groupA_tail2.hpp" 
// #include "head3_groupA_tail3.hpp" 
// #include "head4_groupA_tail4.hpp" 
#undef FOO 

#define FOO _groupB_ 
#include "pseudomacro.hpp" 
// "expands" to: 
// #include "head1_groupB_tail1.hpp" 
// #include "head2_groupB_tail2.hpp" 
// #include "head3_groupB_tail3.hpp" 
// #include "head4_groupB_tail4.hpp" 
#undef FOO 

#define FOO _groupC_ 
#include "pseudomacro.hpp" 
#undef FOO 

// etc. 

Estos incluye podía incluso estar en el medio de los bloques de códigos que desea repetir (con FOO alterado), como el haga clic en las solicitudes de Bing Jian: macro definition containing #include directive

No he utilizado este truco extensamente, pero hace mi trabajo. Obviamente se puede ampliar para tener tantos "parámetros" como sea necesario, y puede ejecutar los comandos de preprocesador que desee allí, además de generar el código real. Simplemente no puede usar lo que crea como entrada en otra macro, como puede hacerlo con las macros normales, ya que no puede pegar el include dentro de una macro. Pero puede ir dentro de otra pseudo macro :).

Otros pueden tener algunos comentarios sobre otras limitaciones, y qué podría salir mal :).

+0

Relacionado: http://stackoverflow.com/a/302343/2436175 – Antonio

+1

Suena genial, pero en teoría es no definido en el estándar, y depende de la implementación del compilador. Ver http://stackoverflow.com/questions/20524491/preprocessor-concatenation-for-include-path/20524959#20524959 – Antonio

+0

Ahh, es bueno saberlo, ¡aplausos! –

Cuestiones relacionadas