2009-07-30 13 views
1

Einfach nur neugierig, warum die Vergleichsfunktion für stl :: sort kein statisches Member sein kann?Warum ist stl vergleichen Funktion ein Mitglied?

Ich habe eine kleine Hilfsklasse foo, die in einer Kopfzeile deklariert und definiert ist, aber jetzt muss ich eine foo.cpp-Datei für die Implementierung von cmp() erstellen, damit sie nicht mehrfach definiert wird.

Ich muss auch an einen passend dekorierten Namen denken, so dass fooCmp() nicht mit anderen cmp() kollidiert.

Da es keinen Zugriff auf Membervariablen hat, benötigt eine Vergleichsoperation, die Zugriff auf einen anderen Wert benötigt (z. B. nach Entfernung von foo.bar), den komplexen Bind2nd-Aufruf.

+2

Vergleichsfunktion für 'std :: sort' _can_ kann ein statisches Element sein.Was auch immer Ihr Problem ist, es ist nicht da - zeigen Sie den Code! –

+3

Es hätte geholfen, wenn VC++, wenn Sie eine winzige Sache falsch gewinnen STL, nicht eine Fehlermeldung, die sah aus wie eine Katze über Ihre Tastatur und dann führte die US-Steuer-Code durch die resultierende Perl-Skript. –

+0

Es ist eine Fluch aller C++ - Implementierungen, nicht nur VC++ (obwohl ich hoffe, dass sie es ein wenig in VC10 mit 'static_assert' verbessern). Konzepte würden helfen, aber leider sind sie jetzt tot im Wasser ... –

Antwort

3

Ich bin nicht sicher, was Sie sich beschweren: sein Auftrag kann

std::sort(begin,end)  // use operator< 
std::sort(begin,end,order) // Where order is a functor 

So:

  • Eine Funktion
  • Eine statische Elementfunktion
  • Oder ein Objekt, das sich wie eine Funktion verhält.

Die folgenden Werke für mich:

class X 
{ 
    public: static bool diff(X const& lhs,X const& rhs) { return true;} 
}; 

int main() 
{ 
    std::vector<X> a; 

    std::sort(a.begin(),a.end(),&X::diff); 
} 

Aber wenn die Klasse eine natürliche Ordnung hat, warum dann nicht nur die Betreiber < für die Klasse definieren. Dies ermöglicht Ihnen den Zugriff auf die Mitglieder und wird sich für die meisten Standardcontainer/-algorithmen, die eine Reihenfolge definieren müssen, gut verhalten.

class X 
{ 
    public: bool operator<(X const& rhs) const { return true;} 
}; 
int main() 
{ 
    std::vector<X> a; 

    std::sort(a.begin(),a.end()); 
} 
+0

Sorry, hatte die Defn etwas falsch - ich dachte, ich hätte daran gedacht, dass Sie das nicht tun könnten. –

+0

Sie sollten "free function" zur Liste der Argumente hinzufügen, die an sort übergeben werden können. Auch die Verwendung von & X :: diff ist visuell mehrdeutig mit Zeiger auf Mitglied. Ich denke, es wäre besser, "& (X :: diff)" zu verwenden oder die Zeigerkonvertierung der Funktion implizit "X :: diff" zuzulassen. –

+0

@mgb: Das Beispiel, an das Sie vielleicht denken, ist, wo Ihre Prädikatfunktion selbst eine Vorlage ist. Das Problem besteht darin, dass die Prädikatargumente nicht automatisch abgeleitet werden und Sie sie daher beim Aufruf von std :: sort explizit angeben müssen. –

0

Wenn Sie mit einer mehrfach definierten Vergleichsfunktion zu tun haben, versuchen Sie, die Funktion mit static Verknüpfung zu deklarieren. Dann reicht der Umfang der Funktion nicht über die Kompilierungseinheit hinaus, wo sie gefunden wird.

Das gesagt, Ihr Vergleich "Funktion" muss überhaupt keine Funktion sein, sondern kann stattdessen eine Funktion sein Objekt. Ein Funktionsobjekt ähnelt sehr stark einer Funktion, ist aber als operator() implementiert, das die entsprechenden Parameter innerhalb einer regulären Klasse verwendet. Da es sich um eine reguläre Klasse handelt, können Sie Konstruktorparameter an die Klasse übergeben.

Hier ist ein einfaches Beispiel:

#include <iostream> 
#include <vector> 
#include <algorithm> 

using namespace std; 

class comparator { 
public: 
    bool operator()(int a, int b) { 
     return a < b; 
    } 
}; 

int main(int, char *[]) 
{ 
    vector<int> a; 
    a.push_back(1); 
    a.push_back(3); 
    a.push_back(2); 
    sort(a.begin(), a.end(), comparator()); 
    cout << a << endl; 
} 
0

klingt tatsächlich wie die Funktion in der Klasse deklariert wurde, im Header definiert ist, aber außerhalb der Klasse ohne Inline-Verknüpfung

also so etwas wie:

class foo{ 
public: 
    static bool compare(const foo& lhs,const foo& rhs); 
    ... 
}; 
bool foo::compare(const foo& lhs,const foo& rhs){ 
    ... 
} 

statt

class foo{ 
public: 
    static bool compare(const foo& lhs,const foo& rhs); 
    ... 
}; 
inline bool foo::compare(const foo& lhs,const foo& rhs){ 
    ... 
} 

die erste von denen wird bewirkt, dass die Funktion in jeder Kompilationseinheit definiert wird

#includes "foo.h" 
Verwandte Themen