2016-04-25 8 views
1

Angenommen, ich habe:Wie sollte ich einen Mehrfachvererbungskonflikt von Typen anstelle von Methoden behandeln?

class A { public: using foo_t = int; } 
class B { public: using foo_t = int; } 
class C : public A, public B { } 

ich C::foo_t beziehen möchten. Ja, es muss C::foo_t, nicht C::A::foo_t und C::B::foo_t sein. Offensichtlich beklagt sich der Compiler über Mehrdeutigkeit. Wenn dies Methoden wären, könnte ich virtuelle Vererbung und vielleicht ein Mixin verwenden, um einen Diamanten oder was auch immer zu bilden. Aber was soll ich für Typen tun? Sollte ich nur manuell eine using-Anweisung hinzufügen?

Hinweise:

  • Sie können davon ausgehen, ich behaupte, statisch beide foo_t die gleich sind.
+0

Warum nicht 'mit foo_t = A :: foo_t'? – skypjack

+2

Wo ist deine Diamantenvererbung? Ich kann nur Mehrfachvererbung sehen, C erbt von A und B. – Janosimas

+1

[Diamantvererbung] (https://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem) nur möglich mit mindestens 4 Klassen. – Drop

Antwort

4

Anweisung genügt in der Tat:

class A { public: using foo_t = int; }; 
class B { public: using foo_t = int; }; 
class C : public A, public B { public: using A::foo_t; }; 

int main() { 
    C::foo_t v = 0; 
} 

Auf diese Weise C::foo_t ist definitiv A::foo_t (wie richtig in den Kommentaren vorgeschlagen).
Wenn Sie den foo_t Typen oder einen neuen Typen für C stattdessen definieren mögen, können Sie dies tun, wie es folgt:

class C : public A, public B { public: using bar_t = A::foo_t; }; 

Hier ist ein minimal, komplettes Beispiel, wo die Typen überprüft werden gleich sein mit sfinae anstelle einer statische Behauptung:

#include<type_traits> 

class A { public: using foo_t = int; }; 
class B { public: using foo_t = int; }; 
class C { public: using foo_t = double; }; 

template<class T, class U, 
    std::enable_if_t<std::is_same<typename T::foo_t, typename U::foo_t>::value>* = nullptr> 
class D: public T, public U { public: using T::foo_t; }; 

int main() { 
    D<A, B>::foo_t v = 0; 
    // the line below does not compile 
    //D<A, C>::foo_t v = 0; 
} 
+0

Die Accessoren hinzugefügt. – einpoklum

+0

Ich weiß, es ist genug, aber ist es das Richtige (TM)? – einpoklum

+0

Sie möchten mit 'C' einen Typ freilegen. Welche Art? Dies ist ein vernünftiger Weg, um es zu definieren, und natürlich ist dies * ein richtiger *. – skypjack

Verwandte Themen