2010-02-01 14 views
0

Donc, cette question a été posée auparavant, mais je voulais une question avec certains de ces mots clés dans le titre.ID numérique unique pour une classe modélisée utilisant l'adresse de fonction

Le problème est simple: Comment puis-je avoir une classe modélisée, de sorte que pour chaque instance du modèle - mais pas chaque instance de la classe - il existe un identifiant numérique unique?

C'est un moyen de différencier:

foo<int> f1; 
foo<char> f2; 
classID(f1) != classID(f2); 

mais,

foo<int> f3; 
foo<int> f4; 
classID(f3) == classID(f4); 

liés à:

in C++, how to use a singleton to ensure that each class has a unique integral ID?

Assigning Unique Numerical Identifiers to Instances of a Templated Class

Répondre

3
template<class T> 
class Base 
{ 
public: 
    static void classID(){} 
private: 
    T* t; 
}; 

int main() 
{ 
    Base<int> foo; 
    Base<int> foo2; 
    Base<char> foo3; 

    /* 
    unsigned int i = reinterpret_cast<unsigned int>(Base<int>::classID); 
    unsigned int ii = reinterpret_cast<unsigned int>(Base<char>::classID); 
    unsigned int iii = reinterpret_cast<unsigned int>(Base<int>::classID); 
    /*/ 
    unsigned int i = reinterpret_cast<unsigned int>(foo.classID); 
    unsigned int ii = reinterpret_cast<unsigned int>(foo2.classID); 
    unsigned int iii = reinterpret_cast<unsigned int>(foo3.classID); 
    //*/ 

    return ((i != ii) + (i <= ii) + (i >= ii)) == 2; 
} 

Voilà comment! C'est léger, super facile, et n'utilise pas RTTI, bien qu'il utilise le reinterpret_cast ridiculement dangereux.

Bien que, peut-être qu'il me manque quelque chose?

+0

J'ai choisi ma propre réponse parce qu'il est a) plus simple et b) le temps de compilation statique constante , Autant que je sache. – Narfanator

+0

J'ai testé cela avec VS 2015 et cela fonctionne lors de la compilation pour Debug mais pas lors de la compilation pour Release. Lors de la compilation pour Release, l'optimiseur combine toutes les fonctions classID() en une seule. Donc, foo.classID == foo2.classID == foo3.classID. – adigostin

+0

Merde. Doit trouver un nouveau truc, maintenant ... – Narfanator

1

Je pense que vous pouvez simplement utiliser une fonction statique pour cela, et d'hériter de sa catégorie:

struct IdCounter { static int counter; }; 
int IdCounter::counter; 

template<typename Derived> 
struct Id : IdCounter { 
    static int classId() { 
    static int id = counter++; 
    return id; 
    } 
}; 

struct One : Id<One> { }; 
struct Two : Id<Two> { }; 

int main() { assert(One::classId() != Two::classId()); } 

Bien sûr, ce ne sera pas une constante de temps de compilation statique - je ne pense pas qu'il est possible automatiquement (vous devrez ajouter manuellement ces types à une liste de type comme mpl::vector). S'il vous plaît noter que pour juste comparer les types pour l'égalité, vous n'avez pas besoin de tout cela. Vous avez juste besoin d'utiliser is_same (dans boost et d'autres bibliothèques et trivial d'écrire) ce qui donne un temps de compilation constante

template<typename A, typename B> 
struct is_same { static bool const value = false; }; 
template<typename A> 
struct is_same<A, A> { static bool const value = true; }; 

int main() { char not_true[!is_same<One, Two>::value ? 1 : -1]; } 
+0

Le problème avec '' is_same'', AFAIK, est qu'il ne supporte pas> ou <, ce qui signifie qu'il n'est pas triable et ne peut donc utiliser aucun objet de stockage efficace comme un arbre ou une carte. – Narfanator

+0

Cela répond à toutes les exigences, cependant, vous faites remarquer que ce n'est pas une constante de temps de compilation statique? Savez-vous si ma propre réponse est? (Je pense que ce serait, mais je ne suis pas sûr de savoir comment tester cela.) – Narfanator