template (Klassen)-Problem



  • Man sagt ja, das man den Wald vor lauter Bäumen nicht sieht. Aber hier weiss ich nicht mal, ob es über Bäume gibt die man sehen könnte.

    Nimm es mir bitte nicht übel, aber ich verstehe weder die Problemstellung, noch was du wirklich willst.

    Um vielleicht etwas Licht in diese Template "Hölle" zu bringen,
    folgender Vorschlag

    template<class K> 
    class find_in
    {
    public:
       //diese sind keine Member Variablen!!
      typedef std::map<K, std::string> t_MAP;
      typedef t_MAP::iterator t_ITER;
      typedef t_MAP::reserve_iterator t_RES_ITER;
    
    private:
      //static const std::map<K, std::string> LookInMAP; ?? was soll das ergegeben
      //static -> also nur einmal
      //const -> niemals ändern
      //LookInMap ?? reference? oder pointer?, wäre noch okay
      //aber eine statische konstante Map warum, wofür, wogegen??
    
    public:
       //fkt ist geraten
       t_ITER search(t_ITER first,t_ITER last,const string& s)
       {
         while(first!=last)
         {
           if((*fist).second==s) 
              break;
    
           first++;
         }
         return fist;
       }
       //fkt ist geraten // bin nicht sicher ob
       t_RES_ITER search(t_RES_ITER last,t_RES_ITER first,const string& s)
       {
         while(last!=fist)
         {
           if((*last).second==s) 
              break;
         }
         return last;
       }   
    };
    

    Zu deinem Comilerfehler

    template<typename I, typename K> 
                find_in<I,K>::I   //hm, wat is'n ::I 
          //typename of template oder
          //Klasse oder was
          //müsste ich mal durch'n Comiler jagen um mehr zu raten, sagen
                find_in<I,K>::make_IB(
    

    trotztdem weiß ich nicht wofür das alles gut sein soll.

    Wie wär's mit der STL zum Beispiel

    #include <algorithm>
    template<class InputIterator, class T>
    InputIterator std::find(InputIterator fist,InputIterator last,const  T& value);
    //oder 
    std::find_if(...);
    


  • Nachtrag:

    template<typename I, typename K> 
     find_in<I,K>::MAP_IT_b 
         find_in<I,K>::make_IB
    
              (std::map<K, std::string> MAP/*????*/)
    { 
                    return MAP.rbegin(); //???
                } 
    
    Iterator_oder_so find_in( copy of MAP)//
    {
        return MAP.rbegin();//map ist wech, nach return
    }
    

    Okay, Okay,
    aber wie du siehst was ich nicht was du willst



  • hallo idefix,
    danke erst mal fuer Deine Geduld!
    Was will ich eigentlich:
    In unterschiedlichen map's (<unsigned long,string> und <size_t,string>) soll
    das letzte Vorkomen eines strings (nennen wir ihn LAST_OPEN) gefunden werden,
    und wahlweise (geflagte Uebergabe) den Iterator bzw. Reverse_Iterator
    zurueckgeben.
    Soviel zu zur Specifikation.
    Haette vielleicht noch mitbemerken sollen, dass dies meine erste wirkliche
    template-Geschichte (class oder nur Funktion?) ist. Deine Info's:

    public: 
       //diese sind keine Member Variablen!! 
      typedef std::map<K, std::string> t_MAP; 
      typedef t_MAP::iterator t_ITER; 
      typedef t_MAP::reserve_iterator t_RES_ITER;
    

    hat meinem Verstaendis fuer die Funktionalitaet von templates allemal weitergeholfen.
    Grundlegende Schwierigkeiten hab ich im Fall der template Klasse (wie unschwer
    zu bemerken war) mit der Deklaration von klassenspezifischen Konstanten, wie:

    private: 
      //static const std::map<K, std::string> LookInMAP; ?? was soll das ergegeben 
      //static -> also nur einmal 
      //const -> niemals ändern 
      //LookInMap ?? reference? oder pointer?, wäre noch okay 
      //aber eine statische konstante Map warum, wofür, wogegen??
    

    Kann ich denn eine statische konstante Map durchlaufen (will ja nur ihren
    Inhalt nicht veraendern). Aber da hab ich noch Defizite, vorallem mit POintern und Referenzen!!
    Meine Gruende waren:

    private: 
      static const std::map<K, std::string> LookInMAP; // soll nicht veraendert werden koennen
      // als Member habe ich besseren Zugriff drauf??
    

    Dein Vorschlag:

    #include <algorithm> 
    template<class InputIterator, class T> 
    InputIterator std::find(InputIterator fist,InputIterator last,const  T& value); 
    //oder  
    std::find_if(...);
    

    verwirrt mich, da ich Iteratoren bzw. Reverse_Iteratoren nicht eindeutig den
    unterschiedlichen Iterator-Kategorien (Input-, Output-, Forward-, Bidirectional- und Random Access-) zuorden kann 😕
    Ein Reverse_Iterator kann In- und Output, kann aber kein Forward-, Bidirectional-, oder Random Acces Iterator sein..., ein Iterator kann In- und
    Output, und ist ein Forwarditerator.
    Um "das letzte Vorkommen" zu finden wuerde sich ja eigentlich der
    Reverse_Iterator anbieten, leider funktioniert der aber nicht mit z.B. erase(p).
    Aber ich will nun auch zu weit vom Thema weg. Werde nun versuchen Deine Anregungen zu verwenden, und zum Ziel zu kommen 🙄
    Schau mer mal...

    Danke
    SF



  • Auch n Nachtrag:
    der Aufruf wollte ich folgende Argumente mit auf den Weg geben:

    - die map // ist schon member einer anderen Klasse und duerfte eh nicht veraendert werden koennen
    - den zu suchenden string LAST_OPEN
    - die Flagge, Iterator oder Reverse_Iterator



  • So jetzt erkläre mir doch noch mal was du willst.
    Wer soll wann einen iterator oder reserve_iterator zurückgeben?
    Und wie soll das letzte Element gefunden werden. Bedinung

    //////////
    //dieses template ist aus der STL nach empfunden std::find
    template<class InIt, class T>
        InIt find_item(InIt first, InIt last, const T& val)
    {
    	while(first!=last)
    	{
    		if((*first).second==val)
    			break;
    
    		first++;
    	}
    	return first;
    }
    //////////
    
    class CAutos
    {
    public:
    	typedef std::map<unsigned long, std::string>  MY_MAP;
    private:
    	MY_MAP m_AutoMap;
    
    	public:
    	bool getLast(const std::string& s)
    	{
    		MY_MAP::iterator Iter;
    
    		Iter=find_item(m_AutoMap.begin(),m_AutoMap.end(),s);
    
    		return Iter!=m_AutoMap.end() ? true:false;
    	}
    
    	void add(const MY_MAP::value_type& val)
    	{
    
    		m_AutoMap.insert(val);
    	}
    };
    
    class CKarten
    {
    public:
    	typedef std::map<std::string::size_type, std::string>  MY_MAP;
    private:
    	MY_MAP m_KartenMap;
    
    public:
    	bool getLast(const std::string& s)
    	{
    		MY_MAP::iterator Iter;
    
    		Iter=find_item(m_KartenMap.begin(),m_KartenMap.end(),s);
    
    		return Iter!=m_KartenMap.end() ? true:false;
    	}
    
    	void add(const MY_MAP::value_type& val)
    	{
    		m_KartenMap.insert(val);
    	}
    };
    
    int main(int argc, char* argv[])
    {
    	CKarten karten;
    
    	karten.add(CKarten::MY_MAP::value_type(23,"herz"));
    	karten.add(CKarten::MY_MAP::value_type(234,"pik"));
    	karten.add(CKarten::MY_MAP::value_type(2345,"karo"));
    	karten.add(CKarten::MY_MAP::value_type(2341,"herz"));
    
    	if(karten.getLast("karo"))
    	{
    		std::cout<<"letzte Karte gefunden!"<<std::endl;
    	}
    	else
    	{
    		std::cout<<"karte nicht da!"<<std::endl;
    	}
    
    	CAutos Autos;
    
    	Autos.add(CAutos::MY_MAP::value_type(23,"audi"));
    	Autos.add(CAutos::MY_MAP::value_type(234,"opel"));
    	Autos.add(CAutos::MY_MAP::value_type(2345,"VW"));
    	Autos.add(CAutos::MY_MAP::value_type(2341,"Porsche"));
    
    	if(Autos.getLast("opel"))
    	{
    		std::cout<<"letztes Auto gefunden!"<<std::endl;
    	}
    	else
    	{
    		std::cout<<"Auto nicht da!"<<std::endl;
    	}
    
    	if(Autos.getLast("toyota"))
    	{
    		std::cout<<"letztes Auto gefunden!"<<std::endl;
    	}
    	else
    	{
    		std::cout<<"Auto nicht da!"<<std::endl;
    	}
    
    	printf("Hallo Welt!\n");
    	return 0;
    }
    


  • hi,

    also, der Aufruf soll (z.B.) so lauten:

    // map<unsigned long,string> Analyse;
    // map<unsigned long,string>:: iterator Ana_It;
    Ana_It = find_in::MAPPE(Analyse,LAST_OPEN,false);
    
    // oder
    
    // map<size_t,string> tags;
    // map<size_t,string>:: reverse_iterator R_TAGS;
    R_TAGS = find_in::MAPPE(tags,LAST_OPEN,true);
    

    wobei die eigentliche Suche meines Erachtens so laufen sollte:

    // iterator-Variante(benutze hier gleiche Namen wie oben):
    map<unsigned long,string>::iterator Anfang = Analyse.begin();
    map<unsigned long,string>::iterator Ergebnis = Analyse.end();
    while(Anfang != Analyse.end()){
        if(strcmp((*Anfang).second).c_str(), LAST_OPEN.c_str()) == 0)
            Ergebnis = Anfang;
        ++Anfang;
    }
    
    // oder
    
    map<size_t,string>::reverse_iterator Anfang = Analyse.rbegin();
    map<size_t,string>::reverse_iterator Ergebnis = Analyse.rend();
    while(Anfang != Analyse.end()){
        if(strcmp((*Anfang).second).c_str(), LAST_OPEN.c_str()) == 0){
            Ergebnis = Anfang;
            break;
        }
        ++Anfang;
    }
    

    der (reverse_)iterator Ergebnis zeigt bei Definition auf's Ende, falls aber LAST_OPEN gefunden wird, wird er mit entsprechendem (reverse_)iterator
    ueberschrieben.
    Naja, und dafuer wollt ich halt ein template schreiben, dass alle 4 Varianten berücksichtigen kann.

    Im Moment haeng ich noch immer an folgendem Problem: "syntax error before `<' token", an folgender Stelle

    template<typename I, typename K>
                find_in<I,K>::MAP find_in<I,K>make_IB(LookInMAP){  // hier, ist die zweite (das Argument "LookInMAP" tut auch noch nicht, soll die map sein)
                    return LookInMAP.begin();
                }
    
    // find_in (momentaner, nicht fehlerloser Stand)
    template<typename I, typename K>
        class find_in{
            private:
                typedef std::map<K, std::string> MAP;
                MAP LookInMAP;
                static bool REVERSE;    // ob der hier noetig ist...
    
            public:
                I make_IB(MAP);    // Implementation oben
                I make_IE(MAP);
    
                I MAPPE(LookInMAP, std::string LAST_OPEN, bool REVERSE);
            };
    

    Nach meinem Verstaednis muss die Implementation wie folgt anfangen:
    classname<x,y>::RUECKGABE classname<x,y>::FUNKTIONSNAME(*classname<x,y>*ARGUMENT){
    ...
    }
    Bei "classname<x,y>::FUNKTIONSNAME" bekomme ich aber den Compile-Fehler, und versteh halt nicht warum.

    Soviel zu "was ich will", nun zum STL-Beispiel:
    Das hier ist geht schon mal in ne gute Richtung,

    template<class InIt, class T> 
        InIt find_item(InIt first, InIt last, const T& val) 
    { 
        while(first!=last) 
        { 
            if((*first).second==val) 
                break; 
    
            first++; 
        } 
        return first; 
    } 
    
    class CAutos 
    { 
    public: 
        typedef std::map<unsigned long, std::string>  MY_MAP; 
    private: 
        MY_MAP m_AutoMap; 
    
        public: 
        bool getLast(const std::string& s) 
        { 
            MY_MAP::iterator Iter; 
    
            Iter=find_item(m_AutoMap.begin(),m_AutoMap.end(),s); 
    
            return Iter!=m_AutoMap.end() ? true:false; 
        } 
    };
    

    aber leider ermoeglicht es nicht die reverse_iterator UND die iterator -Moeglichkeit.
    Will ich denn zu viel?

    Um's nicht zu lang und unverstaendlich zu machen belass ich's mal hierbei.
    Schoene Gruesse
    SF



  • hm, wie wärs mit:

    bool getFirst(const std::string& s)
    {
    MY_MAP::reverse_iterator Iter;
    
    Iter=find_item(m_AutoMap.rbegin(),m_AutoMap.rend(),s);
    
    return Iter!=m_AutoMap.rend() ? true:false;
    }
    

    Ich möchte dir nicht in deinen Quelltext reinfuhrwerken, aber das Template funzt schon mal. Mit iterator und reserve_iterator.

    Ich denke, das du von einem Template etwas anders erwartes als es dir wirklich bieten kann. Ein Template ist nicht dazu gemacht zu casten oder Typenprüfung zu um gehen.

    Deinen Compilerfehler:

    Nach meinem Verstaednis muss die Implementation wie folgt anfangen:
    classname<x,y>::RUECKGABE classname<x,y>::FUNKTIONSNAME(classname<x,y>ARGUMENT){
    ...
    }

    Dann mach das doch was du Vorschlägst!??
    Bis auf classname<x,y>::RUECKGABE ist es richtig. weil was ist void,int,double
    gibt es nicht scope von classname<x,y>::.

    template<class I,class K> class test
    {
    
    	public:
    		I mappe();
    };
    
    template<class I,class K> I test<I,K>::mappe()
    {
    	I j;
    
    	return j;
    }
    

    Bis heute weiß ich immer noch nicht was class I ist.



  • was ich nicht ganz raff, ist die Funktionalitaet bzw. der Hintergrund von: getFirst(const std::string& s); das sagt doch nur gefunden oder eben nicht?
    in Deinem Bsp.: getFirst(const std::string& s) benutzt Du einen reverse_iterator, damit kann's ja nicht mehr mit einem iterator funktionieren.

    das template soll nicht casten oder die Typenpruefung umgehen, da die Rueckgabe aber sowohl ein iterator als auch reverse_iterator sein koennen soll,
    muss die Rueckgabe in der Deklaration variabel sein, oder lieg ich da falsch?

    idefix schrieb:

    Deinen Compilerfehler:

    Nach meinem Verstaednis muss die Implementation wie folgt anfangen:
    classname<x,y>::RUECKGABE classname<x,y>::FUNKTIONSNAME(classname<x,y>ARGUMENT){
    ...
    }

    Dann mach das doch was du Vorschlägst!??
    Bis auf classname<x,y>::RUECKGABE ist es richtig. weil was ist void,int,double
    gibt es nicht scope von classname<x,y>::.

    dafuer (variable Rueckgabe) hatte ich eigentlich classname<x,y>::RUECKGABE gedacht, nachdem RUECKGABE eben als template deklariert wurde 😕

    idefix schrieb:

    template<class I,class K> class test
    {
    
    	public:
    		I mappe();
    };
    
    template<class I,class K> I test<I,K>::mappe()
    {
    	I j;
    
    	return j;
    }
    

    Bis heute weiß ich immer noch nicht was class I ist.

    class I war der erste und falsche Weg, mittlerweile heisst es typename I, und soll sowohl iterator und reverse_iterator handlen koennen, weiss aber ob das so tut!

    muss denn in Deinem Bsp.: find_item(InIt first, InIt last, const T& val) die Rueckgabe (iterator bzw. reverse_iterator) in der Deklaration nicht angegben sein? Oder uebernimmt das die template<class InIt, class T> ??

    So, nun hast etwas Nerv-Pause, muss ein par Tage weg, womit das Problem aber nur aufgeschoben ist...

    Schoenes Wochenende
    SF



  • Danke. Wünsche ebenfalls ein schönens Wochenende gehabt zu haben.

    Der Unterschied von typename und class in einer Templatedeklaration, kann vieleicht jemand anderes näher Erläutern. Ist aber nicht unbedingt falsch, eher nicht nötig.

    Zugegeben getFirst und getLast hätter ich besser searchForward und searchBackward benennen sollen. Diese Funktionen sollten auch nur zeigen, dass die Templatefunktion find_item sowohl Iteratoren als auch Reserve_Iteratoren oder besser jegliche Arten von Datentypen verträgt. Der Funktionsinhalt nicht!!! Das ist aber noch nicht relevant. Der Compiler löst dieses Template dann dementsprechend auf.

    Um deinen Compiler-Fehler vieleicht besser in den Griff zubekommen, könntest du ja mal versuchen die Funktionen in den Scope des Templates zu lassen.

    template<typename I, typename K> 
    class find_in{ 
    private: 
    typedef std::map<K, std::string> MAP; 
    MAP LookInMAP; 
    static bool REVERSE;    // ob der hier noetig ist... 
    
    public: 
    //I make_IB(MAP& LookInMAP) //wäre besser, aber wird wohl später kommen
    I make_IB(MAP LookInMAP)
    {
      return LookInMAP.begin(); 
    } 
    };
    

    wenn du jetzt die Implementierung außerhalb deklarierst

    template<typename I, typename K> //template
    I //Rückgabe 
    find_in<I,K>make_IB(find_in<I,K>::MAP LookInMAP)//Funktionskopf
    //find_in<I,K>make_IB(MAP LookInMAP)//Könnte auch so sein, weil du schon im Scope bist
    {                  
     return LookInMAP.begin(); 
    }
    

    Easy Go. Oder? Wie du vieleicht bemerkst sieht dieses Template dem find_item sehr ähnlich. Wenn auch etwas undeutlich.

    das template soll nicht casten oder die Typenpruefung umgehen, da die Rueckgabe aber sowohl ein iterator als auch reverse_iterator sein koennen soll,
    muss die Rueckgabe in der Deklaration variabel sein, oder lieg ich da falsch?

    Ich vage mal die Behauptung das ein Template nur das kann was eine "normale" Funktion/Klasse auch kann.

    var foo(){ retrun int(0);}
    var foo(){ retrun char(0);}
    var foo(){ retrun double(0.0);}

    Das geht schon, ist aber ein ganz anders Thema und ich würde es dir nicht als Lösung deines Problems empfehlen. Templats reichen völlig aus, solange du nur Algorithmen verallgemeinern willst. Wirst sehen.

    template<class T> T foo(){return T(0);} // zum Beispiel



  • Das klingt ja schon recht vielversprechend. Das einzige Problem, welches ich
    bezueglich der eigentlichen (Such-)Funktion ohne Ueberladung seh, ist dass die
    Schleife mit reverse_iterator bei Fund (Uebereinstimmung) abgebrochen werden
    muss, und beim iterator aber nicht abgebrochen werden darf.
    Ebenso sollte "make_IB" im ersten Fall map.rbegin(), im zweiten Fall
    map.begin() zuruckgeben...

    Naja, aber frueher oder spaeter wird das schon, und ich werd die template-
    Funktionen dann auch ein wenig mehr begriffen haben (hoffentlich).
    Vor Mi. komm ich vermutlich aber nicht mehr dazu.

    solong und danke
    SF


Anmelden zum Antworten