Construir ruta para la directiva #include con macro

Me gustaría incluir rutas de archivos creadas dinámicamente por una macro para una parte dependiente de la configuración de destino de mi progtwig.

por ejemplo, me gustaría construir una macro que se invocaría así:

#include TARGET_PATH_OF(header.h) 

Que se ampliará a algo como esto:

 #include "corefoundation/header.h" 

cuando la fuente está configurada (en este caso) para OSX

Hasta el momento, todos los bashs han fallado. Espero que alguien haya hecho esto antes?

ejemplo de lo que no funciona:

 #include  #include  #define Dir directory/ #define File filename.h #define MakePath(f) BOOST_PP_STRINGIZE(BOOST_PP_CAT(Dir,f)) #define MyPath MakePath(File) using namespace std; int main() { // this is a test - yes I know I could just concatenate strings here // but that is not the case for #include cout << MyPath << endl; } 

errores:

 ./enableif.cpp:31:13: error: pasting formed '/filename', an invalid preprocessing token cout << MyPath << endl; ^ ./enableif.cpp:26:16: note: expanded from macro 'MyPath' #define MyPath MakePath(File) ^ ./enableif.cpp:25:40: note: expanded from macro 'MakePath' #define MakePath(f) BOOST_PP_STRINGIZE(BOOST_PP_CAT(Dir,f)) ^ /usr/local/include/boost/preprocessor/cat.hpp:22:32: note: expanded from macro 'BOOST_PP_CAT' # define BOOST_PP_CAT(a, b) BOOST_PP_CAT_I(a, b) ^ /usr/local/include/boost/preprocessor/cat.hpp:29:36: note: expanded from macro 'BOOST_PP_CAT_I' # define BOOST_PP_CAT_I(a, b) a ## b ^ 1 error generated. 

Tiendo a estar de acuerdo con el comentario en la respuesta de utnapistim de que no deberías hacer esto aunque puedas. Pero, de hecho, puede, con comstackdores de C que cumplen con los estándares. [Nota 1]

Hay dos problemas para superar. El primero es que no puede usar el operador ## para crear algo que no sea un token de preprocesador válido, y los nombres de ruta no califican como toques de preprocesador válidos porque incluyen / y . caracteres. (The . Estaría bien si el token comenzara con un dígito, pero el / nunca funcionará).

En realidad, no necesita concatenar tokens para poder escribirlos con el operador # , ya que ese operador codificará un argumento de macro completo, y el argumento puede consistir en múltiples tokens. Sin embargo, stringify respeta el espacio en blanco [Nota 2], por lo que STRINGIFY(Dir File) no funcionará; dará como resultado "directory/ filename.h" y el espacio extraño en el nombre del archivo hará que el #include falle. Entonces necesita concatenar Dir y File sin ningún espacio en blanco.

Lo siguiente resuelve el segundo problema usando una macro de función que simplemente devuelve su argumento:

 #define IDENT(x) x #define XSTR(x) #x #define STR(x) XSTR(x) #define PATH(x,y) STR(IDENT(x)IDENT(y)) #define Dir sys/ #define File socket.h #include PATH(Dir,File) 

Tenga en cuenta que se conservará un carácter de espacio en blanco en la llamada a PATH . Entonces Path(Dir, File) fallará.

Por supuesto, no necesitaría la complicación de la macro IDENT si pudiera escribir la concatenación sin espacios. Por ejemplo:

 #define XSTR(x) #x #define STR(x) XSTR(x) #define Dir sys #define File socket.h #include STR(Dir/File) 

Notas

  1. Lo probé con clang, gcc e icc, como está disponible en godbolt . No sé si funciona con Visual Studio.

  2. Más exactamente, se semi-respeta el espacio en blanco: el espacio en blanco se convierte en un único carácter de espacio.

Me gustaría incluir rutas de archivos creadas dinámicamente por una macro para una parte dependiente de la configuración de destino de mi progtwig.

No deberías poder (y si puedes hacerlo, probablemente no deberías hacer esto).

Está tratando de hacer el trabajo del comstackdor en un archivo fuente, lo cual no tiene mucho sentido. Si desea cambiar las rutas incluidas en función de la máquina en la que comstack, este es un problema resuelto (pero no resuelto en un archivo de encabezado).

Solución canónica:

Use una IF en su Makefile o CMakeLists.txt, use páginas de propiedades personalizadas según la configuración de comstackción en Visual Studio (o simplemente establezca las configuraciones particulares para su comstackción en el entorno del sistema operativo para su usuario).

Luego, escriba la directiva include como:

 #include  // no path here 

y confíe en el entorno / sistema de comstackción para hacer que la ruta esté disponible cuando se invoca el comstackdor.

Según su descripción, parece que descubrió que no todos los "" son una cadena. En particular, #include "corefoundation/header.h" parece una cadena común pero no lo es. Gtwigticalmente, el texto citado fuera de las directivas del preprocesador está destinado al comstackdor y se comstack para anular los literales de cadena terminados. El preprocesador interpreta el texto citado en las directivas de preprocesador de una manera definida por la implementación.

Dicho esto, el error en su ejemplo se debe a que Boost pegó el segundo y tercer token: / y filename . El primer, cuarto y quinto token ( directory h Y h ) no se modifican. Esto no es lo que querías, obviamente.

Es mucho más fácil confiar en la concatenación automática de cadenas. "directory/" "filename" es el mismo literal de cadena como "directory/filename" Tenga en cuenta que no hay + entre los dos fragmentos.

Esto funciona para VS2013. (Por supuesto, se puede hacer más fácil).

 #define myIDENT(x) x #define myXSTR(x) #x #define mySTR(x) myXSTR(x) #define myPATH(x,y) mySTR(myIDENT(x)myIDENT(y)) #define myLIBAEdir D:\\Georgy\\myprojects\\LibraryAE\\build\\native\\include\\ //here whitespace! #define myFile libae.h #include myPATH(myLIBAEdir,myFile) 
    Intereting Posts