2015-11-20 3 views
5

nehme ich eine Vorlage T definieren, die eine verschachtelte Klasse der Template-Parameter P wie folgt verwendet:Mit verschachtelten Klasse von Template-Parameter in CRTP

template<class P> class T 
{ 
public: 
    T(P& p) : p(p) {} 
    P& p; 
    typename P::Nested& get_nested() { return p.nested; } 
}; 

Wenn ich eine Klasse deklarieren A mit dem Namen eine verschachtelte Klasse umfasst

class A 
{ 
public: 
    class Nested 
    { 
    public: 
     int i; 
    }; 
    Nested nested; 
}; 

void test2a() 
{ 
    A a; 
    a.nested.i = 1; 
    T<A> t_a(a); 
    t_a.get_nested().i = 2; 
} 

Nun, ich habe eine Klasse B erklären will, die in der gleichen Art und Weise, eine verschachtelte cla beinhaltet: Nested, kann ich eine Variable vom Typ T<A> ohne Probleme definieren ss namens Nested und erbt von T<B> wie folgt:

class B : public T<B> 
{ 
public: 
    class Nested 
    { 
    public: 
     int i; 
    }; 
    Nested nested; 
}; 

Compilation des obigen Codes wird mit Fehler: „Nested kein Mitglied von B ist

Ich glaube, ich verstehe, was passiert: Zum Zeitpunkt der Eingabe der Vorlage ist die Klasse B wegen Vererbung unvollständig definiert.

aber ich frage mich, ob es eine Möglichkeit, so etwas zu tun ist ...

Vielen Dank für Hilfe.

Antwort

3

konnte ich Ihr Beispiel haben, mit einfach kompilieren

template<class P> class T 
{ 
public: 
    T(P& p) : p(p) {} 
    P& p; 
    auto& get_nested() { return p.nested; } 
}; 

Einem anderen Ansatz, den gleichen Tricks wie @ecatmur ausnutzt, aber ein bisschen einfacher:

template<class R = P> 
typename R::Nested& get_nested() { return p.nested; } 

Und hier hat der Compiler die Auswertung von P::Nested zu verschieben, bis Sie get_nested() aufrufen.

+0

Vielen Dank für diese Tricks, Petr und Ecatmur. Allerdings verwende ich MSVC 2010 Compiler, die keine von ihnen kompilieren werden. Ich denke ernsthaft darüber nach, auf einen C++ 14-kompatiblen Compiler zu aktualisieren ... jetzt. Wie auch immer, vielen Dank für deine Antworten. – shrike

+0

@SharpDressedMan, was ist das genaue Problem und exakte Fehlermeldung mit meiner zweiten Lösung? Es scheint sogar C++ 03 für mich zu sein ... – Petr

+0

Fehler ist C4519: Standardschablonenargumente sind nur für eine Klassenvorlage zulässig. – shrike

6

Sie müssen die Auflösung des Rückgabetyps von get_nested verzögern, bis sie aufgerufen wird.

Eine Möglichkeit, dies zu tun, ist der Rückgabetyp abhängig von einem Template-Parameter zu machen:

template<typename unused = void> 
    typename std::conditional<false, unused, P>::type::Nested& 
    get_nested() { return p.nested; } 

Ein anderer Weg (da C++ 14) Rückgabetyp Abzug zu verwenden:

auto& get_nested() { return p.nested; } 
Verwandte Themen