ne kurze frage zu templates



  • hi,
    ich habe vor eine klasse zu schreiben, die eine dynamisch verwaltete Matrix
    darstellen soll (zeilen und spalten koennen nachtraeglich hinzugefuegt oder entfernt werden).
    Nun wollte ich fuer diese klasse die datentypen fuer die einzelnen zellen variabel halten, habe also bei der deklaration template-klasse verwendet.

    Ich moechte nun, dass z.B. bei einfuegen einer neuen zeile die datenelemente der zeile initial auf bestimmte default-werte gesetzt werden (z.B. wenn datentyp string ist, dann sollen die zellen per default "defaultstring" zugewiesen bekommen sein, wenn datentyp int ist, dann -1 etc. wobei ich irgendwo im programm-code angeben kann, was der default-wert fuer den jeweiligen datentypen ist.

    Ich weiss nur nicht wie das im programm-code zu bewerkstelligen ist, da ich erst zur laufzeit den datentypen kenne:

    z.B.:

    DATATYPE default_value()
    {
       // hier entsprechend den default-value zurueckgeben jenachdem was DATATYPE 
    }
    
    template<DATATYPE>
    void foo()
    {
    // matrix bekommt an bestimmter stelle einen default wert zugewiesen
    ...
    mat[r][c] = default_value();
    ...
    }
    

    danke,gruss



  • hat keiner ne idee 😞 ?
    ich konnte, da es eher eine spezielle frage ist, kaum informationen hierueber finden. Das Forum hier ist also meine einzige informationsquelle momentan 🙂

    wenn die frage nicht verstanden worden sein sollte, formuliere ich sie natuerlich gerne noch mal anders.

    danke vorab.



  • muck schrieb:

    Ich weiss nur nicht wie das im programm-code zu bewerkstelligen ist, da ich erst zur laufzeit den datentypen kenne:

    Falsch, du kennst ihn zur Compilezeit.

    Du musst das Template spezialisieren.

    template<>
    int matrix<int>::default_value() { return 4711; }
    
    template<>
    string matrix<string>::default_value() { return "foo"; }
    
    // ...
    


  • ja du hast recht. ich meinte nur was anderes habs nur falsch formuliert:

    den datentyp kenne ich zur compilezeit, aber ich kenne ihn noch nicht DAVOR 🙂

    bevor ich Deinen Typ ausprobiere:
    wie sieht denn die deklaration der beiden beispiel-member die Du gepostet hast aus???

    also:

    template<DATATYPE>
    class Matrix
    {
      // und nu??
    };
    
    // hier wuerde das ausimplementierte von Dir kommen ...
    

    gruss



  • template<DATATYPE>
    class Matrix
    {
      DATATYPE default_value();
    };
    
    // hier wuerde das ausimplementierte von Dir kommen ...
    

    Wobei ich das nicht über eine Funktion, sondern sofort über eine Konstante lösen würde. Di Funktion macht ja im Prinzip nix ausser eine Konstante zurückzugeben und ist somit nutzlos.



  • Obwohl ich nicht sicher bin, ob der Ansatz so sinnvoll ist... Soweit ich weiß kann man doch keine Klassenmember spezialisieren...
    Falls das verwirrend ist:

    template<class T>
    class foo
    {
        const int i;
        void rt();
    };
    
    template<>
    class foo<int>
    {
        //was jetzt?? Ich will nur einwas spezialisieren, und nicht alles neu schreiben
    };
    

    Ich würde das über eine externe Spezialisierungssammlung lösen:

    namespace matrix_defaults
    {
        template<class T>    //Standardwert
        struct default
        {
            static const T d;    //nicht alle kompiler erlaube die initialisierung an dieser Stelle...
        };
        template<class T>
        const T default<T>::d=T();
    
        template<>
        struct default<std::string>
        {
            static const string d;
        };
        template<>
        const string default<string>::d="foo";
    };
    

    Wie gesagt bin ich mir aber nicht sicher, ob man statische member einzeln spezialisieren kann...
    /ich seh grade, in welcher beziehung ist default ein Schlüsselwort?



  • ness schrieb:

    /ich seh grade, in welcher beziehung ist default ein Schlüsselwort?

    Als Standardzweig einer switch-Anweisung.



  • ness schrieb:

    Ich würde das über eine externe Spezialisierungssammlung lösen:

    namespace matrix_defaults
    {
        template<class T>    //Standardwert
        struct default
        {
            static const T d;    //nicht alle kompiler erlaube die initialisierung an dieser Stelle...
        };
        template<class T>
        const T default<T>::d=T();
    
        template<>
        struct default<std::string>
        {
            static const string d;
        };
        template<>
        const string default<string>::d="foo";
    };
    

    Das:

    template<>
        const string default<string>::d="foo";
    

    muss

    const string default<string>::d="foo";
    

    heißen und gehört in eine cpp-Datei, da es sich bei der expliziten Spezialisierung nicht mehr um ein Template handelt.



  • Oh? Und welche Bedeutung hat das Schüsselwort 'default' in diesem Zusammenhang?



  • Helium schrieb:

    Oh? Und welche Bedeutung hat das Schüsselwort 'default' in diesem Zusammenhang?

    Nur eine: es bedeutet, dass ich irrtümlicherweise annahm, dass Mitdenken hier durchaus erwünscht ist und ich deshalb einfach Copy&Paste verwenden kann statt mir einen passenden Namen einfallen lassen zu müssen und den Code zu ändern.
    Aber Danke der Nachfrage 🙄



  • vielen dank fuer die antwort(en).
    sorry dass ich nochmal nachhaken muss:

    #include <iostream>
    #include <string>
    using namespace std;
    
    template<class A, class B>
    class Foo
    {
    public:
    	static B d();
    };
    
    template<class A>
    string Foo<A, string>::d(){return "test";}
    
    int main(int argc, char *argv[])
    {
    	cout << Foo<string>::d() << endl;
    	return 0;
    }
    

    eigentlich muss ich, wie man oben an meinem (vergeblichem) versuch sieht, eine spezialisierung eines templates vornehmen, in dem nur ein template-parameter spezialisiert wird (meine klasse hat also zwei template-parameter).

    nur die syntax der klassen-methode d() ist nicht ganz richtig und ich weiss nicht warum !?! weiss jemand wie es heissen muesste fuer obiges beispiel?

    danke vorab.



  • Das geht so nunmal nicht. Du müsstest wenndann die ganze Klasse spezialisieren.



  • hmmm. ist das eigentlich ne "schwaeche" von C++ oder gibt es einen bestimmten grund warum man sowas vielleicht nicht machen koennen soll?

    momentan sehe ich keinen grund warum ich bei mehreren template-parametern nicht einzelne davon spezialisieren koennen soll!?

    wie auch immer, danke vorab.

    gruss.



  • c++ hat ne menge Schwächen, die sicher irgendwann ausgebügelt werden. Es ist nur so, das manche dinge die als Schwäche erscheinen in wirkleichkeit keine sind.



  • deshalb ja auch meine konkrete frage ob das im obigen fall eine "schwaeche" ist oder tiefergehende gruende existieren, die sowas verbieten.

    ein kleines beispiel warum ich sowas ueberhaupt versuche (vielleicht ist ja mein denkansatz falsch):

    man stelle sich eine klasse Graph vor:

    template<class NODEDATA, class EDGEDATA>
    class Graph
    {
      public:
        // ...
        // hier nun irgendwelche methoden mit denen man einen graphen erstellen,
        // manipulieren kann
        // ...
    
        // folgende methode soll default-werte fuer kanten-daten liefern
        static EDGEDATA default_edge_value();
    };
    
    template<class NODEDATA>
    string Graph<NODEDATA, string>::default_edge_value(){return "something";}
    
    template<class NODEDATA>
    string Graph<NODEDATA, int>::default_edge_value(){return -1;}
    
    int main(int argc, char *argv[])
    {
      Graph<string, string> g;
      Graph<int, string> g2;
    
      cout << Graph<string, string>::default_edge_value() << endl;
      cout << Graph<int, string>::default_edge_value() << endl;  
    
      return 0;
    }
    

    ich moechte nun, egal welchen typ ich fuer NODEDATA angebe, fuer den fall dass EDGEDATA ein string ist, "something" zurueckliefern.
    wieso werde ich nun gezwungen NODEDATA auch noch zu spezialisieren???

    vielleicht schiesse ich mir ja durch meine denkweise momentan selbst in den fuss, weiss es nicht.

    danke.



  • Ich glaube es würde nicht mal klappen wenn du komplett explizit spezialisierst...



  • kann mir vielleicht jemand sagen, ob er eine gute (schon getestete und wenns geht portable) Library fuer Matrizenberechnungen/Vektoralgebra fuer C++ kennt?

    (die blitz++ library habe ich mir schon angesehen, aber die soll fuer beispielsweise Visual C++ nicht funzen)

    danke, gruss.



  • Das die nicht funktioniert liegt nur an der nicht-standard-konformität der msvc. Beim msvc 7.1 funktioniert sie meines Weiisens... Wenn ich du wäre würde ich nie auf eine Bibliothek verzichten, nur weil sie auf einem Kompiler nicht funktioniert, weil der nicht standardkonform genug ist.
    /mal ganz davon abgesehen, warum setzt du nicht einfach die angebotene Lösung um?



  • ok das habe ich nicht genau genug gelesen, danke.

    mit libraries habe ich im allgemeinen nicht so tolle erfahrungen gemacht.
    man muss schon meinungen anderer einholen.
    Es gibt selbsternannte libraries zu hauf, aber ob die gut funktionieren ist ne andere sache.

    hat jemand erfahrungen mit der genannten lib?

    vielen dank.



  • Soweit ich wiß soll blitz++ ganz gut sein. Die Arithmetik von tinyvector basiert auf template-metaprogramming-> sauschnell. Und auch die normale matrizenklasse soll um längen schneller sein als std::valarray...
    achja: klappt unser Vorschlag oder bekommst du es nicht hin? (Um nicht nur off-topic zu posten 😃 )


Anmelden zum Antworten