2011-01-20 17 views
18

Estoy intentando generar el nombre de archivo de inclusión en macro. Esto se supone que es social en C++:Generar incluir nombre de archivo en una macro

#define INCLUDE_FILE "module_impl_win.hpp" 
#include INCLUDE_FILE 

esto funciona bien, pero tan pronto como trato de nombre de archivo generado se failes para compilar

#define INCLUDE_FILE(M) M##"_impl_win.hpp" 
#include INCLUDE_FILE("module") 

En realidad me da la advertencia en MSVC2010

C4067 advertencia: fichas inesperados siguiente directiva de preprocesador - que se espera un newlin

pero no incluye el archivo.

¿Cuál es el problema? ¿Cómo puedo deshacerme de eso?

Respuesta

18

Haría esto usando una macro de cotización de ayudante. Algo como esto le dará lo que quiere:

#define QUOTEME(M)  #M 
#define INCLUDE_FILE(M) QUOTEME(M##_impl_win.hpp) 

#include INCLUDE_FILE(module) 
+1

Tienes que tener cuidado con este enfoque.'_impl_win' es un token identificador y dado que comienza con un guión bajo (y está en el espacio de nombres de la macro), está reservado para la implementación. Deberías separar el '_' inicial y concatenarlo por separado, aunque no estoy seguro de cómo hacerlo aquí ya que' _' es un identificador reservado. –

+1

Por cierto, ¿qué tan portátil es? – ledokol

+0

@James McNellis: Standard solo reserva los nombres con un guion bajo seguido de un carácter en mayúscula (o nombres que contengan doble guion bajo). No sé por qué Sutter recomienda evitar el uso del subrayado en todas partes. – ledokol

3

El problema es que con el tiempo su código se vería así:

#include "module""_impl_win.hpp" 

Esto genera la misma advertencia y error que está viendo pero de una manera un poco más evidente.

Mientras que el compilador aceptará esa sintaxis, el preprocesador no lo hará.

No tengo una sugerencia para hacer lo que está tratando de hacer el trabajo. Personalmente, no querría usar ese tipo de macro, ya que hace que sea más difícil navegar el código visualmente y es probable que impida que muchos editores naveguen rápidamente por el código.

+0

Gracias, no sabía que concatena cadenas así. Imagine que hay cientos de archivos que incluyen encabezados específicos de plataforma con #ifdef ... #endif. Si mañana agregaré soporte para una plataforma más, entonces necesitaría editar todos estos archivos en lugar de solo editar una macro y agregar archivos de implementación específicos de la plataforma. Eso es triste. – ledokol

+0

@ledokol: ¿Por qué la funcionalidad específica de la plataforma no puede dividirse en encabezados separados y archivos fuente que no están incluidos en ningún otro lugar? Debería ser fácil consolidar la funcionalidad específica de la plataforma y dependiente de la plataforma en un conjunto relativamente pequeño de archivos. –

+0

¿Quiere decir por qué PIMPL no se usa para separar el código específico de la plataforma? Bueno, no se puede usar en todas partes. Hay muchas clases de plantillas que requieren una declaración de clase de implementación específica de la plataforma. Así que tengo que dividirlo en archivos de cabecera e implementación. – ledokol

3

También puede impulsar el uso del preprocesador, especialmente los BOOST_PP_STRINGIZE/BOOST_PP_CAT macros:

#include <boost/preprocessor/cat.hpp> 
#include <boost/preprocessor/stringize.hpp> 

#define INCLUDE_FILE(M) BOOST_PP_STRINGIZE(BOOST_PP_CAT(M, _impl_win.hpp)) 

// expands to: #include "module_impl_win.hpp" 
#include INCLUDE_FILE(module) 

(cf. C Macro - DynamiC#include)

Tenga en cuenta que este sufre el mismo problema que la respuesta de @ Andrew (encabezado subrayado = identificador reservado).

Cuestiones relacionadas