2012-06-20 11 views
5

Kennt jemand eine Methode, CRTP zu verwenden, um die Anzahl der Unterklassen eines Objekts zu zählen?Wie zählt man die Anzahl der CRTP-Unterklassen einer Template-Klasse?

Angenommen wir ein Setup ähnlich wie die folgenden hatten:

template <typename T>  
class Object 
{ 
    .... 
}; 

const unsigned int ObjectSubClassCount = ...; 

class Subobject : public Object<SubObject> 
{ 
    .... 
}; 

class Second : public Object<Second> 
{ 
    .... 
}; 

und so weiter, so dass unter Verwendung von TMP, könnten wir haben eine Konstante (ObjectSubClassCount), die die Gesamtzahl der Unterklassen repräsentiert?

Kennt jemand einen Weg, dies zu tun?

Edit: Ich wünsche das Ergebnis als Template-Parameter verwenden später, also muss ich es mit TMP ...

+0

Nur um zu bemerken, arbeite ich, um dieses Problem zu lösen, mich. Ich frage Sie nur für den Fall, dass ich es nie tue, oder Sie tun es zuerst. – Serge

+0

Sollte möglich sein - möchten Sie einen Zähler für die Unterklassen auf jeder Hierarchieebene oder nur die ganze Anzahl der Unterklassen des Objekts haben? – duselbaer

+0

Nur die Unterklassen auf dieser Ebene; Keine Hierarchie erwarten. – Serge

Antwort

2

Ohne die Anforderung später als Template-Parameter das Ergebnis verwenden getan werden würde ich versuche es so:

// Class which increments a given counter at instanciation 
struct Increment { 
    Increment(std::size_t& counter) 
    { 
    counter++; 
    } 
}; 

// This is your template base 
template <typename T>  
class Object 
{ 
    private: 
    // For every instanciation of the template (which is done for a subclass) 
    // the class counter should get incremented 
    static Increment incrementCounter; 
}; 

// This is the global object counter 
static std::size_t classCounter; 

// Static Member Variable 
template<typename T> 
Object<T>::incrementCounter(classCounter); 

Habe es nicht versucht aber sollte tun. Um das Ergebnis wieder als Template-Parameter zur Verfügung zu haben (MPL) habe ich nicht genug Erfahrung in MPL, aber ich bezweifle, dass dies möglich ist.

0

Ok, ich bin also auf eine ... akzeptable Antwort gestoßen. Ich dachte mir, dass es nicht funktionieren würde, wenn die Unterklassen absolut kein Wissen voneinander hätten (ich meine, wir sprechen von einer funktionalen Programmierung ...).

Hier ist eine Lösung dafür. Es ist definitiv nicht die Lösung, die ich mir wünschen würde; Es ist jedoch ein Anfang. Ich habe alle Objekte gezwungen, eine Form von CRTP zu verwenden, aber eine, die mehr von einem verknüpften Listenformat verwendet.

A: selbst und B: die jüngste zuvor definierten Unterklasse

hier ist mein Code für diese (ich benutze eine Vorlage aus Auf diese Weise müssen unsere Subklassen von einem Objekt <> Templat abgeleitet werden <type_traits> einmal, nur eine Note)

template <typename T> //SFINAE check for the existance of subclasscount static member 
struct has_subclasscount 
{ 

    template <typename U> 
    static typename std::enable_if<sizeof(U::subclasscount) != 0, int>::type test(int); 

    template <typename U> 
    static char test(...); 

    static const bool result = (sizeof(test<T>(0)) == sizeof(int))?(true):(false); 
}; 


template <bool res, typename T> 
struct return_subclasscount //the value to return is 0 if false 
{ 
    static const int result = 0; 
}; 


template <typename T>  
struct return_subclasscount<true, T> //returns subclasscount only if the first parameter is true 
{ 
    static const int result = T::subclasscount; 
}; 


template <typename T>    //combines return_subclasscount and has_subclasscount 
struct get_subclasscount 
{ 
    static const int result = return_subclasscount<has_subclasscount<T>::result, T>::result; 
}; 


template <typename This, typename Prev> 
class Object 
{ 
public: 

    static const int subclasscount = 1 + get_subclasscount<Prev>::result; //the subclass count 
}; 


class sub1 : public Object<sub1, int> 
{ 

}; 


class sub2 : public Object<sub2, sub1> 
{ 

}; 


class sub3 : public Object<sub3, sub2> 
{ 

}; 

Diese letzten drei leere Klassen sind die Unterklassen, die wir zählen. Dies ist unsere Header-Datei. In unserer CPP-Datei, die wir haben:

Welche, dass es funktioniert hat bestätigt:

int main() { 

std::cout << sub3::subclasscount; 

char c; 
std::cin >> c; 
} 

es Rennen, wir eine einfache Ausgabe von zu bekommen. Jetzt , einige der Nachteile dieser Lösung:

  • Wir müssen wissen, was unsere letzte definierte Unterklasse war, bevor wir hinzufügen, auf.
  • Wir müssen mit dem Zähler der Unterklasse mithalten, indem wir ihn immer von der letzten Unterklasse in der Liste abändern (dies kann durch Verwendung einer konsistenten "endoflist" Unterklasse vermieden werden, die stattdessen beibehalten werden müsste)

Upsides, obwohl die Tatsache, dass wir keine unserer zuvor definierten Unterklassen aufrechterhalten müssen.Ich betrachte diese Antwort jedoch eher als "Ausgangspunkt" als als "endgültige Lösung". vielleicht etwas, das erweitert werden kann?

(auch dies kann leicht eine Form der Baumstruktur machen missbraucht werden, wo subclasscount tatsächlich die Tiefe von jedem beliebigen Knoten im Baum darstellen würde)

Wer irgendwelche Ideen von hier aus?