Maps mit Structs



  • Liebe Alle,

    Ich habe ein kleines Problem mit einer map mit eigenem struct.

    Das Struct sieht folgendermaßen aus.

    struct State{
    	list<EclipseTerm> trueL;
    	list<EclipseTerm> notTrueL;		
    
    	bool operator<(const State& A) const
    		{ return trueL.size()<A.trueL.size(); }
    
    	bool operator==(const State& A) const
    		{ if((trueL == A.trueL) && (notTrueL == A.notTrueL) )
    			{return true; }
    		else
    			{return false; }
    
    			}		
    	};
    

    nun will ich solche States als Key einer Map haben, erlebe aber immer wieder, dass ein Eintrag, der an sich noch gar nicht existiert angeblich in der Map sei.

    Hier ist die Schleife, in der ich Versuche zu mappen.

    list<Terminal>::const_iterator terminal_it;
    	list<Goal>::const_iterator goal_it;	
    
    	map<State,int> finals;
    
    	for(terminal_it = terminals.begin(); terminal_it != terminals.end(); terminal_it++)
    	{
    
    		for(goal_it = goals.begin(); goal_it != goals.end(); goal_it++)
    		{
    			Terminal tempTerminal = *terminal_it;
    			Goal tempGoal = *goal_it;
    
    			State tempState = State();
    			// merge beide true listen
    			tempGoal.trueL.merge(tempTerminal.trueL);
    			tempState.trueL = tempGoal.trueL;
    
    			// merge beide not true listen
    			tempGoal.notTrueL.merge(tempTerminal.notTrueL);
    			tempState.notTrueL = tempGoal.notTrueL;		
    
                            // Hier lasse ich mir den State ausgeben, der angeblich schon in der Map drin sein soll. Es ist definitiv nicht der gleiche  
    			if(finals.find(tempState) != finals.end()){
    				State nochmehrtemp = (*finals.find(tempState)).first;
    				cout << "In der Map " << nochmehrtemp.trueL << " " << nochmehrtemp.notTrueL  << endl;
    				cout << "mein Vergleich " << tempState.trueL << " " << tempState.notTrueL  << endl;				
    			}
    
                            // Einfügen in Map
    			finals[tempState] = tempGoal.points;	
    
    			State temp = (*finals.begin()).first;
                            // Hier ein Test, der den == Operator überprüft. Funktioniert einwandfrei
    			cout << "gleichheit " << (temp == tempState) << endl;
    
    		}
    
    	}
    

    Meine Einträge werden ab dem zweiten immer wieder überschrieben. Es scheint, als würde nur mit der zweiten Liste verglichen werden, statt mit beiden, aber ich verstehe nicht warum.

    Wer kann helfen?



  • std::map verwendet zum Vergleichen lediglich den op<, nicht den op==. 2 Objekte a und b gelten dann als gleich, wenn gilt !(a < b) && !(b < a) .
    In deinem Fall sind deshalb für die map 2 State-Objekte dann gleich, wenn ihre trueL-Listen die gleiche Länge haben.
    Die Lösung besteht hier meines Wissens nur in einem verbesserten op<, zum Beispiel mit einer lexiographischen Sortierung.



  • Danke! Werds veruschen. (Klingt sehr logisch -.-)



  • Du hast einen op< und einen op== implementiert, dass lässt vermuten dass du von find() erwartest, dass op== benutzt wird. Das ist aber NICHT der Fall.
    std::map benutzt nur einen Comparator, im default-Fall std::less, was wiederum den operator< benutzt.
    Mit diesem einen Comparator wird sowohl die Ordnung in der map hergestellt als auch sämtliche Key-Vergleiche durchgeführt. Dabei ist im Sinne der map a == b, wenn !(a < b) && !(b < a).
    Für deine map sind also zwei Elemente gleich, wenn die Länge der ersten Liste bei beiden gleich ist.


Anmelden zum Antworten