2009-05-18 6 views
0

I haben die folgende Datenstruktur:mehrere functors für Vektor um Sortierfunktion neu zu definieren

typedef vector< vector<int> > MxInt2d; 
typedef vector< vector<double> > MxDouble2d; 

class QSweep{ 
public: 
.... 
static MxDouble2d myPoints_; 
MxInt2d myEdges_; 
MxInt2d sweepEvents; 

class order{ 
public: 
    bool operator() (const vector<int>& edge1, const vector<int>& edge2){ 
      return (myPoints_[edge1[0]][0]<myPoints_[edge2[0]][0])|| 
         (myPoints_[edge1[0]][0]==myPoints_[edge2[0]][0]&& 
         myPoints_[edge1[0]][1]<myPoints_[edge2[0]][1]) 
        || 
        (myPoints_[edge1[0]][0]==myPoints_[edge2[0]][0]&& 
         myPoints_[edge1[0]][1]==myPoints_[edge2[0]][1]&& 
        getSlope(myPoints_[edge1[0]][0],myPoints_[edge1[0][1], 
            myPoints_[edge1[1]][0],myPoints_[edge1[1]][1]) 
        < 
         getSlope(myPoints_[edge2[0][0],myPoints_[edge2[0][1],  
            myPoints_[edge2[1]][0],myPoints_[edge2[1]][1])); 
        } 
}; 
static double getSlope(double a, double b, double c, double d); 
static double computeDet(double a, double b, double c, double d, double x, double y); 

};

I die Funktors für verwenden, um(), wenn der Konstruktor in der folgenden Weise definieren:

QSweep::QSweep(const MxDouble2d& myPoints, const MxInt2d& myEdges){ 
.... 
    //code here for initializing myPoints_, myEdges_ 
sort(myEdges_.begin(),myEdges_.end(),order()); 
} 

Auf diese Weise sind meine Daten myEdges_ angeordnet sind, wenn die Funktors Reihenfolge initialisiert() verwendet. Nun möchte ich die Daten SweepEvents (die den gleichen Typ wie myEdges_ mit dem vordefinierten Datentyp aus C++ Vektor hat) mit einem völlig anderen Kriterien anordnen, das heißt, ich möchte nicht die Funktion getSlope (...) verwenden, aber die Funktion computeDet (...) für SweepEvents. Also dachte ich, ich brauche noch andere Funktor für die Neudefinition der < von sort() für den Vektordatensatz richtig? So würde ich habe ein neues Funktors Order1(), in dem ich die mit computeDet (...) berechneten Daten verwenden schreiben und dann rufe ich die Art auf meinen sweepEvents Datentypen:

sort(sweepEvents.begin(),sweepEvents.end(),order1()); 

Ich bin nicht sicher, ob Das ist die gute Lösung? kann ich auf verschiedene Arten neu definieren < wenn ich verschiedene Namen für den Funktor verwende? Hat jemand ein paar Vorschläge, wäre ich wirklich dankbar. Vielen Dank im Voraus, madalina

Nein die beiden functors dass sie keinen gemeinsamen Code nicht verwendet.

class orderDet{ 
public: 
    bool operator() (const vector<int>& edgeSW1, const vector<int>& edgeSW2 
           ,const vector<int>& edgeC){ 
     return 
      (
      computeDet(myPoints_[edgeSW1[0]],myPoints_[edgeSW1[1]],myPoints_[edgeC[0]]) 
      < 
      computeDet(myPoints_[edgeSW2[0]],myPoints_[edgeSW2[1]],myPoints_[edgeC[0]]) 
      ); 
    }} 

und ich mag es genannt: Ich habe den zweiten Funktors insede die QSweep Klasse, da dies geschrieben

sort(sweepEvents.begin(), sweepEvents.end(), orderDet()); 

Aber ich bekam die folgenden Kompilierungsfehler:

error: no match for call to '(QSweepComplete::orderDet) (std::vector<int, 
std::allocator<int> >&, std::vector<int, std::allocator<int> >&)' 
./QSweepComplete.h:68: note: candidates are: bool 
QSweepComplete::orderDet::operator()(const std::vector<int, std::allocator<int>>&, 
const std::vector<int, std::allocator<int> >&, const std::vector<int, 
std::allocator<int> >&) 

I Ich vermute, dass der Parameter nicht übereinstimmt, da der dritte Parameter von orderDet (...., edgeC) nicht Teil der SweepEvents-Liste ist, wie die anderen, sondern Teil der Variablen myEdges _...istVielleicht kann man mir ein paar Vorschläge machen, wie man diesen Funktor implementiert?

danke im voraus. Beste Wünsche, madalina

Antwort

4

Wenn Sie 2 verschiedene Sortierkriterien haben, dann sollten Sie 2 verschiedene Funktoren haben.

Geben Sie ihnen aussagekräftige Namen wie:

OrderBySlopes und OrderByXYZ

Wenn der 2 functors einigen gemeinsamen Code verwenden, können Sie dieses Refactoring aus. d.h. in eine Basisklasse

0

Was Glen sagte.

Wenn Sie wirklich wirklich darauf bestehen, dass eine Funktion doppelte Aufgaben hat, können Sie sich darauf verlassen, dass verschiedene Parametertypen zwei Versionen von operator() überladen.

0

Ihr orderDet::operator() benötigt drei Argumente. Die std::sort will nur zwei, um zwei Werte zu vergleichen.

kann eine Lösung sein, die Kanten Vektor als Mitglied Ihrer Funktors hinzuzufügen:

struct orderDet { 
    const vector<int>& edges; 
    orderDet(const vector<int>& edges):edges(edges){}; 

    bool operator()(const vector<int>& v1, const vector<int>& v2) const { 
     .... 
    } 
}; 

By the way, wenn man die Leute den Code verstehen wollen, wenn sie es lesen, ich denke eher, sollten Sie ein typedef für deinen inneren Vektor als für den äußeren. Daneben ist es besser, eine Struktur zu definieren, die einen "ersten" und "zweiten" Punkt enthält, als einen sehr generischen Vektor, bei dem nur die ersten beiden Punkte von verwendet werden. Es wird Ihren Code auch lesbarer machen.

Grüße.

+0

ja es hat funktioniert. Vielen Dank. (Ich habe typedef in meinem Code verwendet Ich hätte es auch hier verwenden müssen Sie haben Recht) – madalina

Verwandte Themen