c++ - preprocesamiento - definición de macro que contiene la directiva#include
funcion preprocesador en c++ (9)
¿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.
¿Hay alguna manera de definir una macro que pueda contener la directiva #include
en su cuerpo?
Si acabo de poner el " #include
", da error
C2162: "expected macro formal
parámetro"
ya que aquí no estoy usando #
para concatenar cadenas.
Si uso " /# include
", entonces recibo los siguientes dos errores:
error C2017: illegal escape sequence
error C2121: ''#'' : invalid character : possibly the result of a macro expansion
¿Alguna ayuda?
Contagioso tiene razón, si lo estás haciendo:
myFile.c:
#include "standardAppDefs.h"
#myStandardIncludeMacro
standardAppDefs.h:
#define myStandardIncludeMacro #include <foo.h>
Por qué no solo decir:
myFile.c:
#include "standardAppDefs.h"
standardAppDefs.h:
#include <foo.h>
Y olvida las macros?
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.
Creo que estás bien en que esta tarea parece imposible, ya que también obtuve de
http://groups.google.com/group/comp.lang.c++/browse_thread/thread/03d20d234539a85c#
No, las directivas de preprocesador en C ++ (y C) no son reflectantes.
Pawel Dziepak
De todos modos, la razón detrás de este intento es que estoy tratando de hacer el siguiente fragmento de código repetidamente utilizado 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;
}
}
Para otra tarea, necesito tener una función similar
void bar(AbstractClass object)
donde ubicaré
#include "snippets/bar.cpp"
y, por supuesto, en "snippets / foo.cpp" y "snippets / bar.cpp" está escrito el código específico de la tarea.
No discutiré los méritos, pero freetype (www.freetype.org) hace lo siguiente:
#include FT_FREETYPE_H
donde definen FT_FREETYPE_H en otra parte
No tengo idea de lo que en realidad estás tratando de hacer, pero parece que lo que podrías querer es una función de plantilla.
De esta forma, PixelType es solo un parámetro de plantilla para el bloque de código.
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 mediante concatenación (y trucos como ese), el comportamiento no está definido.
También quería hacer esto, y esta es la razón:
Algunos archivos de encabezado (notablemente mpi.h en OpenMPI) funcionan de manera diferente si está compilando en C o C ++. Me estoy vinculando a un código C MPI de mi programa C ++. Para incluir el encabezado, hago lo de siempre:
extern "C" {
#include "blah.h"
}
Pero esto no funciona porque __cplusplus
todavía está definido incluso en el enlace C. 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
Sorprendentemente, no es solo mpi.h lo 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.
Así que, como dicen los demás, 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 haciendo algo como esto:
Encabezado de macros de Helper:
/* 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 incluyen incluso podría estar en el medio de los bloques de códigos que desea repetir (con FOO alterado), como la respuesta de las solicitudes de Bing Jian: definición de macro que contiene la directiva #include
No he usado 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 podrían tener algunos comentarios sobre otras limitaciones, y qué podría salir mal :).