Optionales Template



  • ichbineinnoob schrieb:

    template <class T>
    class Knoten
    {
    Koordinate k;
    T* anhaengsel;
    };
    
    Knoten<int> knotenInt;
    Knoten<> knotenLeer;
    
    class Knoten
    {
      Koordinate k;  
    };
    
    template <class T>
    class KnotenMitAnhaengsel : public Knoten
    {
      T * anhaengsel;
    };
    
    KnotenMitAnhaengsel<int> knotenInt;
    Knoten knotenLeer;
    

    ?



  • Nein, keine abgeleitete Klasse.

    1 Klasse mit 1 optionaler Template-Variable.

    Das boost::optional Dingens verstehe ich nicht. 😞



  • Eine Spezialisierung geht:

    template<class T = void> // Default void
    class Knoten;
    
    template<>
    class Knoten<void> // Spezialisierung void ohne Anhängsel
    {
        Koordinate k;
    };
    
    template<class T>
    class Knoten // Default mit Anhängsel
    {
        Koordinate k;
        T* anhaengsel;
    };
    
    Knoten<float> k1; // nimmt Default
    Knoten<> k2; // nimmt void-Spezialisierung
    

    (ungetestet)



  • struct none_t {};
    
    template<class T = none_t>
    struct Knoten
    {
       Koordinate k;
       T* anhaengsel;
    };
    
    template<>
    struct Knotwn<none_t>
    {
       Koordinate k;
    };
    

    So vielleicht? Dir ist hoffentlich klar, dass Knoten<> und Knoten<int> zwei verschiedene Typen sind, die nix miteinander zu tun haben. Wahrscheinlich ist das dann mehr nach deinem Geschmack:

    struct KnotenBase
    {
       Koordinate k;
    
       virtual ~KnotenBase() {}
    };
    
    struct none_t {};
    
    template<class T = none_t>
    struct Knoten : KnotenBase
    {
       T* anhaengsel;
    };
    
    template<>
    struct Knoten<none_t> : KnotenBase
    {
       // nix
    };
    

    Aber ich glaube, es wäre für Dich wahrscheinlich von Vorteil, wenn du erklärtest, was du damit bezwecken willst. Dann gibt's ggf. praktischeres Feedback.



  • krümelkacker schrieb:

    Dir ist hoffentlich klar, dass Knoten<> und Knoten<int> zwei verschiedene Typen sind, die nix miteinander zu tun haben.

    Ach so. Nein, ist mir nicht klar.

    Was ich bezwecken möchte? Ich möchte einen Graphen aufbauen und dafür je nach Verwendung verschiedene Knoten benutzen. Je nachdem wofür ich den Graphen brauche und welche Algorithmen ich abspielen möchte, brauche ich verschiedene Daten (Anhaengsel) in den Knoten.

    Ich hatte jetzt an ein Dummy-Struct als normalen Knoten gedacht (also Knoten<void> o.ä.). Aber leere Klassen oder Strukturen lassen sich wohl nicht erzeugen.



  • ichbineinnoob schrieb:

    krümelkacker schrieb:

    Dir ist hoffentlich klar, dass Knoten<> und Knoten<int> zwei verschiedene Typen sind, die nix miteinander zu tun haben.

    Ach so. Nein, ist mir nicht klar.

    Dann ist es sinnvoll, die Gleichartigkeit (hier die Koordinaten) durch eine Basisklasse auszudrücken, bzw. wenn es nur die Koordinaten sind evtl. (falls sinnvoll) davon abzuleiten.

    Eine Hierarchie kannst Du dann mit (Knoten 😉 ausdrücken, unabhängig davon, welcher Typ genau sich hinter (Knoten 😉 verbirgt.

    ichbineinnoob schrieb:

    Was ich bezwecken möchte? Ich möchte einen Graphen aufbauen und dafür je nach Verwendung verschiedene Knoten benutzen. Je nachdem wofür ich den Graphen brauche und welche Algorithmen ich abspielen möchte, brauche ich verschiedene Daten (Anhaengsel) in den Knoten.

    Ist die Anzahl unterschiedlicher Typen begrenzt (z.B. 5 Stück), bzw. kannst eine sinnvolle Schnittstelle erstellen, die Du dann über virtuelle Funktionen rufen kannst?

    ichbineinnoob schrieb:

    Ich hatte jetzt an ein Dummy-Struct als normalen Knoten gedacht (also Knoten<void> o.ä.). Aber leere Klassen oder Strukturen lassen sich wohl nicht erzeugen.

    Knoten<> war nicht leer, es enthielt Koordinaten.



  • Xin schrieb:

    Knoten<> war nicht leer, es enthielt Koordinaten.

    Danke für die Antwort!

    Ich meinte, ich wollte für das T* ein leeres struct {} üebrgeben. Aber das geht leider nicht.



  • ichbineinnoob schrieb:

    Xin schrieb:

    Knoten<> war nicht leer, es enthielt Koordinaten.

    Danke für die Antwort!

    Ich meinte, ich wollte für das T* ein leeres struct {} üebrgeben. Aber das geht leider nicht.

    Das geht, aber das Ding muss einen Namen haben.

    struct Leer
    {};
    
    Knoten< struct Leer > knoten;
    

    Aber Sinn ergibt es keinen, denn ein (struct Leer 😉 ist genauso groß, wie jeder andere Zeiger, also kannst Du auch Knoten< void > nehmen.

    Worauf hier vermutlich jeder hinaus will ist, dass Du eigentlich

    class Knoten
    {
    public:
      Koordinate k;
    
      virtual void MaleDichAufBildschirm( Grafik & g ) = 0;
    };
    
    class KnotenInt
      : public Knoten
    {
    public:  
      int Data;
    
      virtual MaleDichAufBildschirm( Grafik & g )
      {
        /* Frickel das int in die Grafik */
      }
    };
    
    class KnotenString
      : public Knoten
    {
    public:  
      std::string Data;
    
      virtual MaleDichAufBildschirm( Grafik & g )
      {
        /* Frickel den String in die Grafik */
      }
    };
    

    haben willst.

    Alles können als (Knoten 😉 angesehen werden

    Knoten * kInt = new KnotenInt();
    Knoten * kString = new KnotenString();
    

    und alle haben ein identisches Interface:

    kInt->MaleDichAufBildschirm( g );
    kString->MaleDichAufBildschirm( g );
    


  • Eine Basisklasse + Template das von der Basisklasse ableitet und zusätzlich die Daten enthält sollte vollkommen ausreichend sein. Eine "keine Daten" Spezialisierung halte ich nicht für notwendig.
    Wenn man das braucht kann man ja einfach die Basisklasse direkt verwenden.



  • Ich denke, ich habe die Lösung gefunden! 💡

    class Knoten
    {
    Koordinate koordinate;
    void* anhaengsel;
    };
    

    Die Variable "anhaengsel" wäre optional UND man könnte jeden möglichen Typ abspeichern.

    Oder?? 😕



  • Mit void* würde ich nicht arbeiten, da das fehleranfällig ist.

    Eine generische Graphenbibliothek zu schreiben, ist aber auch echt nicht einfach. Ich glaube aber, dass es das ist, was du machen willst. Ich würde da erst mal kleiner anfangen, statt gleich etwas zu kompliziertes basteln, was extrem vielseitig einsetzbar sein soll; denn das gibt's schon: Boost Graph Library.


Anmelden zum Antworten