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.

È stato utile?

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"
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top