2010-05-25 9 views
6

Est-il possible d'utiliser un paramètre de modèle de constante non-type dans une directive de préprocesseur? Voici ce que je pense:Utilisez un paramètre de modèle dans une directive de préprocesseur?

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

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

     // some code here 

     #endif 
    } 
}; 

Quand j'essayer avec quelque chose comme Blah<Foo<0xFFFF>>, VC++ 2010 se plaint quelque chose entre parenthèses inégalés dans la ligne où nous essayons d'utiliser #if. Je devine que le préprocesseur ne sait pas vraiment quoi que ce soit à propos des templates et ce genre de chose n'est tout simplement pas dans son domaine. Que dire?

+0

Juste un point à noter: 'Blah >' n'analyser en c courant ++, vous avez besoin d'un espace entre les '>' s. 'Blah >'. – KitsuneYMG

+0

En fait, dans VC++ 2010, il compile! :) Ils ont partiellement implémenté C++ 0x dans VC++ 2010. – Raj

Répondre

11

Non, ce n'est pas possible. Le préprocesseur est assez bête, et il n'a aucune connaissance de la structure de votre programme. Si T::Doo n'est pas défini dans le préprocesseur (et il ne peut pas l'être, à cause du ::), il ne peut pas évaluer cette expression et échouera.

Cependant, vous pouvez compter sur le compilateur de faire la meilleure chose pour vous:

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

expressions constantes et les branches mortes sont optimisés loin même les paramètres d'optimisation plus bas, de sorte que vous pouvez en toute sécurité faire sans temps d'exécution.

+0

Cela ne va-t-il pas échouer si 'Doo' n'est pas présent dans' T'? –

+0

Merci. C'est ce que je pensais. L'utilisation du compilateur n'est cependant pas idéale pour moi car les membres disponibles dans 'T' dépendent des bits qui sont définis dans' T :: DOO'. Je suis sûr que je m'approche de ce mauvais chemin. Je vais trouver autre chose. Mais était juste curieux de savoir jusqu'où nous pouvons aller avec le préprocesseur. Une autre option pourrait être de voir si des astuces de méta-programmation peuvent être utilisées pour cela. – Raj

+0

Ils peuvent probablement. Si vous ouvrez une nouvelle question avec les détails de ce que vous voulez accomplir, nous pouvons jeter un coup d'œil. – Thomas

2

ce que les membres sont disponibles en T dépend de bits qui sont définis dans T::DOO

Il me semble T::DOO est d'agir comme un identificateur de sous-classe. Donc, je pense que votre Foo et les classes liées doivent être des sous-classes d'une classe qui garantit que DOO est défini.

La clé est: pourquoi devez-vous utiliser un champ de bits?

+0

La réponse à cela est un peu impliqué, mais vous avez tout à fait raison. Je travaille avec cette API (DirectX) qui permet une certaine flexibilité en spécifiant comment vous voulez formater le contenu d'une certaine structure qui est passée en entrée à l'une de ses méthodes. Les informations sur la configuration de la structure sont transmises via un champ de bits. Dans mon application, j'ai 2 abstractions - la première est une classe modèle qui génère une collection d'instances de cette structure avec le champ de bits et la structure elle-même passé en tant qu'arguments de modèle et un autre qui consomme cette collection. Commentaire suite.ci-dessous – Raj

+0

Je voulais écrire du code conditionnel dans la classe grand public qui utilisait des membres spécifiques de cette structure en examinant quels bits sont définis dans le champ de bits. Phew! Je ne suis pas sûr à quel point cela a du sens! Comme il existe diverses instanciations de gabarit de la classe source mappées avec différentes variantes de la structure, le code en question doit être compilé conditionnellement - d'où l'idée d'essayer de voir si le préprocesseur peut être utilisé. – Raj

1

Vous ne savez pas si cela s'applique à votre situation, mais il est possible d'isoler différents cas avec des classes de modèles. Par exemple: (en utilisant une version modifiée de votre code en haut)

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 
    } 
}; 
Questions connexes