2013-06-20 7 views
5

Ich habe Daten in einer C++ - Baumstruktur gespeichert, die ich aus einer Datei eingelesen habe. Der Baum sieht so aus:Kombinieren von Vorlagen und Vererbung in der Baumkonvertierung

Nachdem der Baum gebaut ist, möchte ich es konvertieren, z. zu einer Zeichenfolge.

Um den Baum Code getrennt von dem Conversion-Code zu halten, würde Ich mag Vorlagen verwenden, also so etwas wie das Implementieren:

template <class T> 
T WhiteNode::Convert() { ... }; 

Da jedoch die Baumknoten als BaseNode* gespeichert sind, I don weiß nicht, wie man auf eine solche Template-Member-Funktion zugreift. Und da Template-Member-Funktionen nicht vererbt werden können, glaube ich nicht, dass das funktioniert.

ich mit einer Arbeitslösung hat kommen, aber:

class BaseConversion { 
public: 
    virtual ~BaseConversion() {} 
    virtual void * FromBlack() = 0; 
    virtual void * FromWhite() = 0; 
}; 

template <class T> 
class Conversion : public BaseConversion { 
public: 
    void * FromBlack(); 
    void * FromWhite(); 
}; 

class BaseNode { 
    std::vector<BaseNode*> children_; 
    virtual void * Convert(BaseConversion * conversion) = 0; 
public: 
    virtual ~BaseNode() {} 
    template <class T> 
    T Convert() { 
    return *static_cast<T*>(Convert(new Conversion<T>)); 
    } 
}; 

class WhiteNode : public BaseNode { 
    void * Convert(BaseConversion * conversion) { 
    return conversion->FromWhite(); 
    } 
}; 

class BlackNode : public BaseNode { 
    void * Convert(BaseConversion * conversion) { 
    return conversion->FromBlack(); 
    } 
}; 

Und der Transformationslogik kann vollständig getrennt sein:

template <> 
void * Conversion<std::string>::FromWhite() { 
    return new std::string("converting WHITE node to std::string ..."); 
} 

template <> 
void * Conversion<std::string>::FromBlack() { 
    return new std::string("converting BLACK node to std::string ..."); 
} 

Testen der Code:

BaseNode * node = new BlackNode; 
std::cout << node->Convert<std::string>() << std::endl; 
node = new WhiteNode; 
std::cout << node->Convert<std::string>() << std::endl; 

kehrt das erwartete Ergebnis:

converting BLACK node to std::string ... 
converting WHITE node to std::string ... 

Obwohl diese Lösung funktioniert, bin ich mir sicher, dass es viel einfacher gemacht werden kann. Jede andere, einfachere Lösung, die ich gefunden habe, ist gescheitert, z. aufgrund von Typ löschen.

Ich würde jede mögliche Hilfe dafür schätzen. Vielen Dank!

Antwort

2

Etwas ähnlich wie Ihre Lösung, aber ohne void *.

class NodeVisitor 
{ 
    virtual void VisitBlack(BlackNode* node); 
    virtual void VisitWhite(BlackNode* node); 
}; 

class BaseNode { 
    std::vector<BaseNode*> children_; 
    ... 
    virtual void visit(NodeVisitor* visitor) = 0; 
}; 

class WhiteNode : public BaseNode { 
    virtual void visit(NodeVisitor* visitor) { visitor->visitWhite(this); } 
}; 

class BlackNode : public BaseNode { 
    virtual void visit(NodeVisitor* visitor) { visitor->visitBlack(this); } 
}; 

Dann

std::string convert(BaseNode* node) 
{ 
    class ConvertVisitor 
     : public NodeVisitor 
    { 
     ConvertVisitor(std::string* res) 
      : m_res(res) 
     { } 

     virtual void VisitBlack(BlackNode* node) 
     { 
      *m_res = // convert black node to string; 
     } 

     virtual void VisitWhite(BlackNode* node) 
     { 
      *m_res = // convert white node to string; 
     } 

     std::string* m_res; 
    }; 

    std::string res; 
    ConvertVisitor visitor(&res); 
    node->visit(&visitor); 
    return res; 
} 
+0

Dank. Das Vermeiden des Void-Pointers ist möglicherweise etwas eleganter. Ich suchte jedoch nach etwas kompakterem, vielleicht ohne Konvertierung oder Besucherklassen. – DonDieselkopf

+0

Das wird nicht komplett machbar sein. Haben Sie C++ 11 Unterstützung? –

+0

Ja, das tue ich. Wenn es eine C++ 11-Lösung gibt, wäre ich neugierig. Ich erwartete tatsächlich eine CRTP-ähnliche Lösung. Aber wenn ich meine Anwendung betrachte, werde ich zunehmend versucht, mich an das Besuchermuster zu halten. Trotzdem ist jede andere Meinung sehr willkommen. – DonDieselkopf

Verwandte Themen