Rufen Sie die Basisklasse für einen Typ in der Klassenhierarchie ab
Lesezeit: 6 Minuten
Ist es möglich, den Basisklassentyp in einer Klassenhierarchie zu erhalten?
Beispielsweise:
struct A{};
struct B{} : public A;
struct C{} : public B;
Ich möchte eine Vorlage, die haben wird typedef Base<T>::Type innen so:
Base<A>::Type == A
Base<B>::Type == A
Base<C>::Type == A
Ist das möglich? Was ist, wenn ich Mehrfachvererbung habe?
Kerrek SB
Klassen in C++ können mehr als eine Basisklasse haben, daher macht es keinen Sinn, eine “get me das Grundeigenschaft.
Die TR2-Ergänzungen enthalten jedoch neue Compiler-unterstützte Merkmale std::tr2::bases und std::tr2::direct_bases, die eine undurchsichtige Typenliste von Basisklassen zurückgibt.
Ich bin mir nicht sicher, ob dies es in C++ 14 schaffen wird oder ob es unabhängig veröffentlicht wird, aber GCC bereits scheint dies zu unterstützen.
Das ist eine Art Typ-Eigenschaft, die ohne Compiler-Magie nicht implementiert werden kann, oder?
– jrok
28. April 13 um 12:13 Uhr
Dies ist für meine Frage besser geeignet, aber ich habe die andere Antwort akzeptiert, da sie in Kombination mit std::conditional mein Problem löst.
– Mircea Ispas
28. April 13 um 12:21 Uhr
@jrok: Nun, offensichtlich nicht, wie würde die Eigenschaft etwas über die Typen im Programm erfahren? Auf der anderen Seite sind dies die Art von Kleinigkeiten, die uns einem vollständigen Reflektionssystem zur Kompilierzeit näher bringen.
– Matthias M.
28. April 13 um 12:40 Uhr
@Felics wie kann das nicht die akzeptierte Antwort sein? Ihre Frage war nicht, ob B ist in der Tat eine Basis von D (Zuordnung zu bool), aber welche B ist D abgeleitet von (one-to-many-Mapping).
– TemplateRex
28. April 13 um 19:43 Uhr
@Felics nebenbei, in Zukunft beschreiben beide Ihre Real Problem und das Problem, das Sie mit Ihrem Lösungsversuch haben. Stack Overflow eignet sich zwar gut zum Gedankenlesen, funktioniert aber noch besser, wenn es nicht sein muss!
Wenn D von B abgeleitet ist oder wenn beide dieselbe Nicht-Union-Klasse sind, wird der Elementkonstantenwert gleich true bereitgestellt. Andernfalls ist der Wert falsch.
Sie können es verwenden, um zu überprüfen, ob eine Klasse die Basisklasse einer anderen ist oder nicht:
std::is_base_of<A, A>() // Base<A>::Type == A
std::is_base_of<A, B>() // Base<B>::Type == A
std::is_base_of<A, C>() // Base<C>::Type == A
Andreas Tomassos
Dies kann je nach Anwendungsfall eine gute Möglichkeit sein. Deklarieren Sie eine Typedef der benannten Basisklasse base in der Basisklasse selbst.
Dann abgeleitete Klassen X erbt es als Typnamen X::base.
So B::base ist A, und C::base ist A.
struct A
{
typedef A base;
};
struct B : A {};
struct C : B {};
template<class X>
void f()
{
typename X::base x;
}
int main()
{
f<B>();
f<C>();
}
Heilige Schwarze Katze
Mit gewissen Einschränkungen ist es möglich!
Jede Base, die auf diese Weise nachweisbar sein muss, muss von einer bestimmten CRTP-Base erben. (Oder möglicherweise eine Art Makro enthalten.)
Sie erhalten eine Liste aller Eltern, auch der indirekten.
Sie verwenden die zustandsbehaftete Vorlagenmetaprogrammierung, um eine Liste von Typen zu erstellen, an die Sie Typen anhängen können, indem Sie eine bestimmte Vorlage instanziieren.
Unter Verwendung einer CRTP-Basis fügen Sie a hinzu friend Funktion für jede Klasse, die auf diese Weise erkannt werden muss. Diese Funktionen werden mit SFINAE unaufrufbar gemacht, aber lediglich in Anbetracht sie während der Überladungsauflösung instanziiert die Vorlage, die die entsprechende Basisklasse an die Liste anfügt.
Sie rufen diese überladene Funktion mit ADL auf, und da Überladungen von allen Basen berücksichtigt und versucht werden, instanziiert zu werden, erhalten Sie eine Liste von Basen.
.
6200400cookie-checkRufen Sie die Basisklasse für einen Typ in der Klassenhierarchie abyes