2010-05-25 14 views
6

¿Es posible utilizar un parámetro de plantilla constante sin tipo en una directiva de preprocesador? Aquí es lo que tengo en mente:¿Usa un parámetro de plantilla en una directiva de preprocesador?

template <int DING> 
struct Foo 
{ 
    enum { DOO = DING }; 
}; 

template <typename T> 
struct Blah 
{ 
    void DoIt() 
    { 
     #if (T::DOO & 0x010) 

     // some code here 

     #endif 
    } 
}; 

Cuando intento esto con algo como Blah<Foo<0xFFFF>>, VC++ 2010 se queja de algo acerca de paréntesis, sin igual en la línea en la que estamos tratando de utilizar #if. Supongo que el preprocesador realmente no sabe nada sobre plantillas y este tipo de cosas simplemente no está en su dominio. ¿Que dice?

+0

Sólo un punto a destacar: 'Bla >' no va a analizar en c actual ++, se necesita un espacio entre los '>' s. 'Blah >'. – KitsuneYMG

+0

¡En realidad, en VC++ 2010 compila! :) Han implementado parcialmente C++ 0x en VC++ 2010. – Raj

Respuesta

11

No, esto no es posible. El preprocesador es bastante tonto y no tiene conocimiento de la estructura de su programa. Si T::Doo no está definido en el preprocesador (y no puede ser, debido a ::), no puede evaluar esa expresión y fallará.

Sin embargo, se puede confiar en el compilador para hacer lo más inteligente para usted:

 if (T::Doo & 0x010) { 
      // some code here 
     } 

Las expresiones constantes y ramas muertas se han optimizado de distancia, incluso a los ajustes de optimización más bajos, por lo que puede hacer con seguridad esto sin ningún tiempo de ejecución arriba.

+0

¿No se puede compilar si 'Doo' no está presente en' T'? –

+0

Gracias. Es lo que pensaba. Sin embargo, usar el compilador no es ideal para mí, porque los miembros que están disponibles en 'T' dependen de qué bits se establezcan en' T :: DOO'. Estoy seguro de que me estoy acercando a esto de la manera incorrecta. Descubriré algo más. Pero solo tenía curiosidad sobre qué tan lejos podemos llegar con el preprocesador. Otra opción podría ser ver si los trucos de meta-programación de la plantilla se pueden utilizar para esto. – Raj

+0

Probablemente puedan. Si abre una nueva pregunta con los detalles de lo que desea lograr, podemos echarle un vistazo. – Thomas

2

lo que los miembros están disponibles en T depende de qué bits se establecen en T::DOO

Me suena como T::DOO está actuando como un identificador subclase. Así que estoy pensando que su Foo y las clases relacionadas deben ser subclases de una clase que garantice que se defina DOO.

La clave es: ¿por qué debe usar un campo de bit?

+0

La respuesta a eso es un poco complicado, pero tienes razón. Estoy trabajando con esta API (DirectX) que permite cierta flexibilidad al especificar cómo se quiere formatear el contenido de una determinada estructura que se pasa como entrada a uno de sus métodos. La información sobre cómo se tiene la configuración de la estructura se pasa a través de un campo de bits. En mi aplicación tengo 2 abstracciones: la primera es una clase de plantilla que genera una colección de instancias de esta estructura con el campo de bit y la propia estructura pasada como argumentos de plantilla y otra que consume esta colección. Comentario contd.debajo de – Raj

+0

Quería escribir un código condicional en la clase de consumidor que hiciera uso de miembros específicos de esta estructura inspeccionando qué bits se configuran en el campo de bit. ¡Uf! No estoy seguro de cuánto de esto tiene sentido! Dado que hay varias instancias de plantilla de la clase fuente asignadas con diferentes variantes de la estructura, el código en cuestión debe compilarse de forma condicional, de ahí la idea de intentar ver si el preprocesador se puede usar. – Raj

1

No estoy seguro si esto se aplica a su situación, pero es posible aislar diferentes casos con clases de plantilla. Por ejemplo: (usando una versión modificada de su código de arriba)

template <typename T, int N> 
struct Blah 
{ 
    void DoIt() 
    { 
     // normal DoIt() code 
    } 
}; 

template <typename T> 
struct Blah<T,5> 
{ 
    void DoIt() 
    { 
     // special DoIt() code for only when N==5 
    } 
}; 
Cuestiones relacionadas