std::map Vergleichsoperator



  • rafilis1982 schrieb:

    Auf die Sortierung kommt es mir ja nicht an.

    Doch, die Sortierung ist für die Map selbst wichtig. Du brauchst auch soweit ich weiß, keinen operator=, sondern einen operator<. Und der darf auch nicht irgendwas vergleichen, sondern muss eine eindeutige Sortierung ermöglichen.



  • rafilis1982 schrieb:

    Vielen Dank für deine Antwort.

    Ich könnte ja z.B. die anzahl der Punkte als Vergleichsobjekt nehmen. Hauptsache der fehler wäre erst mal behoben.

    Auf die Sortierung kommt es mir ja nicht an.

    Aber wie füge ich dann diese Neudefinition eines Vergleichsoperators der map hinzu?

    Brauchst Du nicht. Die map erwartet irgendeinen Vergleichsoperator für die Keys. Wenn der nicht gefunden wird, weil gar keiner definiert wurde, meckert der Compiler.
    Wenns ums Sortieren geht, musst Du übrigens den operator< überladen, nicht ==.
    Man kann der Map auch noch einen extra Prädikat mitgeben, wenn der standardmäßig defninierte Verlgeichsoperator nicht das vergleicht, was man möchte.



  • operator< für eine Map muss allerdings unbedingt die Kriterien für Strict Weak Ordering (oder hier auf Deutsch) erfüllen. Sonst kann die Map nicht richtig funktionieren.

    Gleichheit definiert sich in einer Map übrigens über !(a<b) && !(b<a).



  • Soweit ist alles klar und funktioniert nun auch.

    Eine Frage hätte ich noch.

    Ich hab ein ähnliches Problem mit einem Objekt vom Typ Segment_3.

    Also wollte ich das analog zum ersten Problem lösen:

    bool operator<(const Segment_3& l, const Segment_3& r)
    {
    	return l.vertex(0).x() < r.vertex(0).x();
    }
    

    Wenn ich das tue meckert er aber trotzdem weiter.

    Warum?



  • Es wäre hilfreich, wenn du uns sagst, was exakt, vollständig, im Wortlaut gemeckert wird. 🙂



  • rafilis1982 schrieb:

    Soweit ist alles klar und funktioniert nun auch.

    Eine Frage hätte ich noch.

    Ich hab ein ähnliches Problem mit einem Objekt vom Typ Segment_3.

    Also wollte ich das analog zum ersten Problem lösen:

    bool operator<(const Segment_3& l, const Segment_3& r)
    {
    	return l.vertex(0).x() < r.vertex(0).x();
    }
    

    Wenn ich das tue meckert er aber trotzdem weiter.

    Warum?

    Was meckert er denn an? Die konkreten Fehlermeldungen helfen immer...



  • Entschuldigt, es handelt sich um denselben Fehler wie am Anfang:

    error C2678: Binärer Operator '<': Es konnte kein Operator gefunden werden, der einen linksseitigen Operanden vom Typ 'const Segment_3' akzeptiert (oder keine geeignete Konvertierung möglich)
    


  • Wurde der operator< denn vor dem Benutzen der Map deklariert? Befindet sich die Klasse Segment_3 eventuell in einem Namensraum?



  • Ich habe beide Operatoren global untereinander deklariert:

    bool operator<(const Triangulation& l, const Triangulation& r)
    {
    	return l.number_of_vertices() < r.number_of_vertices();
    } 
    
    bool operator<(const Segment_3& l, const Segment_3& r)
    {
    	return l.vertex(0).x() < r.vertex(0).x();
    }
    

    Bezüglich Namensraum, das stimmt, aber das ist auch bei Triangulation nicht anders und funktioniert trotzdem.

    typedef CGAL::Simple_cartesian<double> SK;
    typedef CGAL::Filtered_kernel<SK> FK;
    struct K : public FK {};
    typedef K::Point_3 Point_3;
    typedef K::Segment_3 Segment_3;
    typedef CGAL::Delaunay_triangulation_3<K> Triangulation;
    


  • Keiner eine Idee? 😕



  • rafilis1982 schrieb:

    Keiner eine Idee? 😕

    Ist der Operator zum Zeitpunkt der Template-Ausprägung auch wirklich bekannt?



  • Ich habe den Operator in der Klasse deklariert die ich includiere.

    Erst dann defniere ich die map. Hab auch schon versucht die Deklaration in der entsprechenden Datei vorzunehmen, wo ich auch die Map definiere, leider ohne Erfolg.



  • Poste vielleicht mal ein Stück Code, du kannst ja das Irrelevante weglassen. Vielleicht hast du irgendwo was übersehen...



  • Building.h:

    #include <QTreeWidget>
    #include <map>
    #include <algorithm>
    #include <iostream>
    using namespace std;
    
    // -------------------- CGAL
    //#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
    #include <CGAL/Simple_cartesian.h>
    #include <CGAL/Filtered_kernel.h>
    #include <CGAL/Delaunay_triangulation_3.h>
    
    typedef CGAL::Simple_cartesian<double> SK;
    typedef CGAL::Filtered_kernel<SK> FK;
    struct K : public FK {};
    typedef K::Point_3 Point_3;
    typedef K::Segment_3 Segment_3;
    typedef CGAL::Delaunay_triangulation_3<K> Triangulation;
    
    bool operator<(const Segment_3& l, const Segment_3& r)
    {
    	return l.vertex(0) < r.vertex(0);
    }
    bool operator<(const Triangulation& l, const Triangulation& r)
    {
    	return l.number_of_vertices() < r.number_of_vertices();
    } 
    
    class Building
    {...
    }
    

    geomview.cpp

    #include "geomview_mesh.h"
    using namespace citygml;
    
    typedef pair<Segment_3,Edge*> mapEdgePair;
    
    int GeomviewMesh::read(vector<Building*> *f)
    {
    map<Segment_3,Edge*> mapEdge;
    }
    


  • a) sollte man niemals using-Deklarativen im Header benutzen. Das verseucht den globalen Namespace und führt das ganze Namespace-System an sich ad absurdum.
    b) vermisse ich ein #include "Building.h" in geomview.cpp.
    c) solltest Du Dir mal allgemein Gedanken darüber machen, was man den Header (Schnittstelle) packen sollte, und was besser nicht.



  • zu a) und c)
    Niemand ist perfekt 😉

    zu b)
    Das entsprechende include befindet sich in geomview.h



  • rafilis1982 schrieb:

    zu a) und c)
    Niemand ist perfekt 😉

    Trotzdem solltest du Tachyons Tipps zur Kenntnis nehmen.

    Erstell bitte einmal eine Funktion, die ein Segment_3 als Parameter nimmt, deklariere sie am gleichen Ort wie der Operator und rufe sie dort auf, wo der Operator benutzt wird.


Anmelden zum Antworten