J'ai récemment tenté de créer une classe is_class
et j'avais besoin d'un moyen pour le compilateur de différencier les types d'énumération et les types de classe pour lesquels les opérateurs de conversion sont définis. Voyant comment les classes, les structures et les unions sont les seuls types compatibles avec les fonctions pointeur vers membre, j'ai décidé de demander au compilateur de déterminer si le type utilisé pour instancier le template is_class
était, à son tour, compatible avec les fonctions pointers-to-member . Après avoir rencontré plusieurs problèmes, j'ai décidé de tester le comportement des énumérations lorsqu'elles étaient utilisées conjointement avec des pointeurs vers des membres et obtenaient des résultats farfelus. Le segment suivant illustre la première bizarrerie:Énumérations et pointeur vers membres
enum ENUM {};
void Test(void (ENUM::*pmem) (void))
{
/* ... */
}
Test(NULL);
Lors de la compilation avec Microsoft Visual C++ 2010, la partie pointeur à membre de la définition de la fonction: (ENUM::*pmem)
est en rouge et la souris sur la déclaration révèle l'erreur:
Error: "ENUM" is not a class type
Cependant, le compilateur parse ce segment sans rencontrer d'erreurs, l'attribution pmem
-NULL
. Il est intéressant pour moi que le compilateur permette de voir comment les types d'énumération ne sont pas des classes, des structures ou des unions et ne peuvent donc pas posséder leurs propres méthodes.
Le deuxième point d'intérêt a surgi lors de la création d'une fonction de modèle, en prenant un pointeur à membre l'argument dont le type varie:
template<class _Ty>
void Test_Template(void (_Ty::*pmem) (void))
{
/* ... */
}
Bien sûr, afin de pouvoir utiliser cette fonction, il doit être explicitement qualifié:
Test_Template<ENUM>(NULL);
Cet appel cependant, génère une erreur indiquant:
invalid explicit template argument(s) for 'void Test(void (__thiscall _Ty::*)(void))'
J'ai corrigé ce problème en créant un modèle de fonction supplémentaire, dont le prototype correspondrait à tout appel qui ne correspondrait pas au prototype de la fonction modèle précédente (qui impliquait l'utilisation d'une ellipse).
Questions:
Pourquoi est une énumération compatible avec les pointeurs-à-membres?
Pourquoi existe-t-il une correspondance exacte lors de l'appel de la fonction
Test
non modèle alors que le compilateur génère une erreur pour la qualification expliciteTest_Template
du modèle?
Il semble que 'T ENUM :: * D;' soit une déclaration syntaxiquement valide. Je ne peux rien trouver qui dit explicitement qu'il est sémantiquement mal formé. Mais s'il est bien formé, ce serait une déclaration pour laquelle la section 8 ne spécifie pas le type de «D», ce qui serait bizarre. – aschepler
merci pour la question, c'est génial de voir des questions au-delà du niveau de base de temps en temps et celui-ci devient mon esprit barattage :) –
g ++ 4.4.5 -std = C++ 0x accepte de même 'Test', mais sur un tentative d'appeler 'Test_Template (static_cast (0))' donne l'erreur "aucune fonction correspondante pour l'appel à' Test_Template (void (ENUM :: *)()) '" –
aschepler