2016-08-09 183 views
3

ich eine einzige Vererbungsklassenhierarchie habe wie folgt definiert:Wie die gemeinsam Eltern von zwei Klassen in einer Klassenhierarchie finden

struct A  { using Parent = void; void fnct() { std::cout << "A\n"; } }; 
struct AA : A { using Parent = A;  void fnct() { std::cout << "AA\n"; } }; 
struct AB : A { using Parent = A;  void fnct() { std::cout << "AB\n"; } }; 
struct AAA : AA { using Parent = AA; void fnct() { std::cout << "AAA\n"; } }; 
struct AAB : AA { using Parent = AA; void fnct() { std::cout << "AAB\n"; } }; 
struct ABA : AB { using Parent = AB; void fnct() { std::cout << "ABA\n"; } }; 
struct ABB : AB { using Parent = AB; void fnct() { std::cout << "ABB\n"; } }; 

Jede Klasse in der Hierarchie ein Alias ​​Parent seine direkten Elternklasse definiert, und eine Mitgliedsfunktion void fnct().

I benötigt, um eine Template-Funktion call_fnct_upto_parent<P,C>(C&) für ein gegebenes Objekt der Klasse P der Klassenhierarchie, fnct() vom Typ Typ C bis zum übergeordneten Objekt alle Mitgliedsfunktionen aufruft C und ein gegebenes Elternklasse, das definieren P . Ich implementiert diese mit SFINAE wie folgt:

template<class P, class C> 
typename std::enable_if<!std::is_same<P,C>::value,void>::type call_fnct_upto_parent(C& c) 
{ 
    c.fnct(); 
    static_assert(!std::is_same<typename C::Parent,void>::value, "parent not found"); 
    call_fnct_upto_parent<P, typename C::Parent>(c); 
} 

template<class P, class C> 
typename std::enable_if<std::is_same<P,C>::value,void>::type call_fnct_upto_parent(C& c) 
{ 
    c.fnct(); 
} 

Funktion call_fnct_upto_parent<P,C>(C&) oben definiert, wie erwartet funktioniert, solange P ist Elternteil von C. Zum Beispiel führt ein Anruf an call_fnct_upto_parent<A>(aaa), wobei aaa vom Typ AAA ist, zu Folgeaufrufen zu aaa.AAA::fnct(), aaa.AA::fnct() und aaa.A::fnct(), die zur Kompilierzeit aufgelöst werden.

Nun wäre Ich mag eine Vorlage Funktion call_fnct_upto_common_parent<Ch,Co>(Co&) definieren, die für ein gegebenes Objekt der Klasse Co und eine gegebenen Klasse Ch der Klassenhierarchie, fnct() vom Co bis zum Typ Objekttyp alle Mitgliedsfunktionen aufrufen P des nächsten gemeinsamen Elternteils zu den Klassen Ch und Co. Beispielsweise würde ein Aufruf an call_fnct_upto_common_parent<AB>(aaa) zu nachfolgenden Aufrufen an aaa.AAA::fnct(), aaa.AA::fnct() und aaa.A::fnct() führen, da Klasse A das nächste gemeinsame Elternteil zu den Klassen AB und ist.

Kann eine solche Funktion implementiert werden und wie? Eine Lösung mit Aufrufen, die zur Kompilierungszeit aufgelöst werden, wäre, wenn möglich, vorzuziehen.

Danke für Hilfe.

Antwort

3

Sie std::is_base_of mit einer ähnlichen Struktur zu Ihrem vorhandenen Code verwenden:

template<class T, class U> 
typename std::enable_if<!std::is_base_of<U,T>::value,void>::type 
call_fnct_upto_common_parent(U& u) 
{ 
    u.fnct(); 
    static_assert(!std::is_same<typename U::Parent,void>::value, "parent not found"); 
    call_fnct_upto_common_parent<T, typename U::Parent>(u); 
} 

template<class T, class U> 
typename std::enable_if<std::is_base_of<U,T>::value,void>::type 
call_fnct_upto_common_parent(U& u) 
{ 
    u.fnct(); 
} 
+0

so einfach wie die ... wußte nicht, 'std :: is_base_of <>'; funktioniert sehr gut, vielen Dank. – shrike