Perché la funzione di confronto stl non è un membro?
-
06-07-2019 - |
Domanda
Solo pigramente curioso perché la funzione di confronto per stl :: sort non può essere un membro statico?
Ho un piccolo foo di classe helper che viene dichiarato e definito in un'intestazione, ma ora devo creare un file foo.cpp per l'implementazione di cmp () in modo che non sia definito in modo multiplo.
Devo anche pensare a un nome adeguatamente decorato in modo che fooCmp () non si scontri con nessun altro cmp ().
Poiché non ha accesso a nessuna variabile membro, qualsiasi operazione di confronto che richiede l'accesso ad un altro valore (ad es. ordina per distanza da foo.bar) richiede la complessa chiamata bind2nd.
Soluzione
Non sono sicuro di cosa ti lamenti:
std::sort(begin,end) // use operator<
std::sort(begin,end,order) // Where order is a functor
Quindi l'ordine può essere:
- Una funzione
- Una funzione membro statica
- O un oggetto che si comporta come una funzione.
Per me funziona quanto segue:
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);
}
Ma se la classe ha un ordinamento naturale, allora perché non definire semplicemente l'operatore < per la classe. Ciò ti consentirà l'accesso ai membri e si comporterà bene per la maggior parte dei contenitori / algoritmi standard che devono definire un ordine.
class X
{
public: bool operator<(X const& rhs) const { return true;}
};
int main()
{
std::vector<X> a;
std::sort(a.begin(),a.end());
}
Altri suggerimenti
Se sei interessato a una funzione di confronto definita in modo multiplo, prova a dichiarare la funzione con static
collegamento. Quindi l'ambito della funzione non si estende oltre l'unità di compilazione in cui si trova.
Detto questo, il tuo confronto " funzione " non è necessario che sia una funzione, ma può invece essere una funzione oggetto . Un oggetto funzione è molto simile a una funzione ma è implementato come operator()
che accetta i parametri appropriati all'interno di una classe normale. Poiché è una classe normale, puoi passare i parametri del costruttore alla classe.
Ecco un semplice esempio:
#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;
}
in realtà sembra che la funzione fosse dichiarato in classe, definito nell'intestazione ma fuori dalla classe senza collegamento in linea
cioè qualcosa di simile:
class foo{
public:
static bool compare(const foo& lhs,const foo& rhs);
...
};
bool foo::compare(const foo& lhs,const foo& rhs){
...
}
anziché
class foo{
public:
static bool compare(const foo& lhs,const foo& rhs);
...
};
inline bool foo::compare(const foo& lhs,const foo& rhs){
...
}
il primo dei quali determinerà la definizione della funzione in ogni unità di compilazione che
#includes "foo.h"