[gelöst] templates für Typen definieren



  • Hallo,

    ich baue gerade ein Template, dass intern Listen und Vektoren bearbeiten und verwalten soll. Dazu müsste ich aber bei meiner Funktion Iterator-Suchen ein paar Typen unterscheiden. Folgendes habe ich nun versucht:

    // Auszug .h
    template <typename Arg_Type, typename Inlay_Type>
    class ListSort
    {
    protected:
      Arg_Type* arg1; // Zeiger auf das Objekt, dass verwaltet werden soll.
    
    public:
      /* c'tor */
      ListSort(Arg_Type* newArg);
    
      /* Position suchen */
      typename Arg_Type::iterator& ListeFindIterator(const size_t& thePosToMove);
    
      // .. viele andere Funktionen
    };
    
    // Auszug .cpp
    
    /* Position suchen */
    // -> Für alles was ich nicht unterstütze
    template <typename Arg_Type, typename Inlay_Type>
    typename Arg_Type::iterator& ListSort<Arg_Type, Inlay_Type>::ListeFindIterator(const size_t& /* thePosToMove */)
    {
      return arg1->end();
      // Suchfunktion nicht unterstützt, also end(),
      // damit Funktionsaufrufer aussteigen.
    }
    // -> Vector
    template <typename Arg_Type, typename Inlay_Type>
    typename Arg_Type::iterator& ListSort<std::vector<Inlay_Type>, Inlay_Type>::ListeFindIterator(const size_t& /* thePosToMove */)
    {
      // Hier kommt dann die eigene Find-Funktion für vector hin.
      return arg1->end();
    }
    // -> List
    // -> etc
    
    // Beispiel für Definition:
    typedef MLObject* MLObjectListeInlay;
    typedef std::vector<MLObjectListeInlay> MLObjectListe;
    
    MLObjectListe MyListe;
    ListSort<MLObjectListe, MLObjectListeInlay> ListeVerwaltung(&MyListe);
    

    Leider stigt mir mein Visual Studio Por 2008 hier mit dem Fehler aus:

    error C3860: Eine template-Argumentliste, die dem Klassen-template-Namen folgt, muss Parameter in der in der template-Parameterliste verwendeten Reihenfolge auflisten.
    error C2995: "Arg_Type::iterator &ListSort<Arg_Type,Inlay_Type>::ListeFindIterator(const size_t &)": Funktionsvorlage wurde bereits definiert.
    

    Natürlich weiß ich das ein Template universal gestaltet sein soll und das ist auch die einzige Funktion in dem ganzen Klassen-Teplate, die ich für die Typen vector, list, etc unterschiedlich gestalten muss.

    Ich hab diese Schreibweise aus verschiedenen Internetseiten und Tutorials übernommen. Leider gibt mir aber keines meiner schlauen Bücher (so aus Papier und gebunden) ein Beispiel dafür, so dass ich vermute, "das Internet lügt".

    Wie müsste ich denn richtig schreiben? Wo finde ich (brauchbare) Lektüre für diesen Fall?

    Danke,
    Stefan



  • Hi stefanjann,

    im Prinzip versuchst du ja das hier:

    #include <vector>
    
    template <typename T, typename U>
    class C {
        void F();
    };
    
    template <typename T, typename U>
    void C<T, U>::F() {
    }
    
    // Geht nicht.
    template <typename T, typename U>
    void C<std::vector<U>, U>::F() {
    }
    
    int main() {
        return 0;
    }
    

    (Member-)Funktionstemplates kann man aber nicht einfach so partiell spezialisieren. Dafür muss man erst die Klasse partiell spezialisieren.

    Das säh in dem Beispiel dann so aus:

    #include <vector>
    
    template <typename T, typename U>
    class C {
        void F();
    };
    
    template <typename T, typename U>
    void C<T, U>::F() {
    }
    
    template <typename U>
    class C<std::vector<U>, U> {
        void F();
    };
    
    template <typename U>
    void C<std::vector<U>, U>::F() {
    }
    

    In welchem Buch du sowas findest, kann ich dir jetzt auch leider nicht sagen.
    Ich denke mal "C++ Templates: The Complete Guide" oder "Modern C++ Design: Generic Programming and Design Patterns Applied" könnten das aber drin haben. 😉

    Edit: Hier stehts auch:
    http://www.gotw.ca/publications/mill17.htm

    Gruß
    Dobi

    PS: Weiß jemand, ob im neuen Standard (Member-)Funktionstemplates partiell spezialisiert werden können?



  • Danke schön,
    so gehts. Compiler machts das jetzt.

    Jetzt kommt noch der Praxis-Test.

    Grüße,
    Stefan



  • Falls du noch an einer anderen (eventuell eleganteren) Lösung Interesse hast:
    Manchmal kanns ja ziemlich nervig sein, die komplette Klasse partiell spezialisieren zu müssen, obwohl du das ja eigentlich nur für eine Memberfunktion haben wolltest.
    Deshalb kann man die partielle Spezialisierung von Funktionen mit Operatorüberladung simulieren.
    Das ganze findest du in "Modern C++ Design" in Kapitel 2.5 oder hier:
    http://accu.org/index.php/journals/385

    Gruß
    Dobi

    PS: Es sieht so aus, als sei es mit 0x auch nicht anders.



  • Danke für den Hinweis, ich schau mir das mal in Ruhe an.

    Glücklicherweise hab ich mein Tamplate jetzt auch so hingekommen, dann ich es nicht mehr spezialisieren muss. std::advance sei dank.


Anmelden zum Antworten