2009-12-18 12 views
5

Tengo una macro, donde uno de los argumentos es un valor enum, que se proporciona sin especificar el ámbito del espacio de nombres. Sin embargo, en algún lugar dentro de la macro, necesito acceder a ella (obviamente, debo definir el espacio de nombres allí), pero parece que no puedo concaturar el nombre del espacio de nombres con el parámetro de la plantilla. Dado el siguiente código de ejemplo, el compilador se queja de que pasting :: and Val doesnt give a valid preprocessor token (funciona bien para concating get y a getVal).Argumento macro de Concat con espacio de nombres

namespace TN 
{ 
    enum Info 
    { 
     Val = 0 
    }; 
} 

#define TEST(a) TN::Info get ## a(){return TN::##a;} 
TEST(Val) 

Entonces, ¿hay alguna manera de hacer este trabajo sin necesidad de utilizar otro argumento y, básicamente, especificando el valor que se utilizará dos veces (por ejemplo, #define TEST(a,b) TN::Info get ## a(){return b;})?

Respuesta

10

## es un operador pegar modo, es decir, se debe hacer una sola expresión de múltiples bits de token y como dice el compilador, ::Val no es de un solo símbolo, se trata de dos fichas.

¿Por qué necesita pensar que necesita el segundo ## en absoluto? Qué pasa con esto

#define TEST(a) TN::Info get ## a() { return TN::a; } 
+0

obviamente estoy pensando en la forma de complejo, gracias – Grizzly

+0

@Grizzly: ¡Irónicamente, todo lo contrario! Mi primer instinto también es concatenar, porque las macros son básicamente la sustitución de texto de buscar y reemplazar. Es cuando te das cuenta de que son más complejos que esto (dado que trabajan en _tokens_ y nuestros cerebros no) que surgen problemas como este. :) –

3

Utilice únicamente ## cuando desee concatenar dos elementos y haga que el compilador trate el resultado como un único token (por ejemplo, un identificador).

En su macro, el primer uso de ## es correcto, ya que está tratando de construir un identificador pegando juntos get y el contenido de a, pero el segundo uso de ## es falso, ya que solo quiere hacer un identificador de los contenidos de a y el operador :: es una entidad separada de eso. GCC se quejará de esto (aunque MSVC++ lo hace).

#define TEST(a) TN::Info get ## a(){return TN::a;} 

debería funcionar.

Cuestiones relacionadas