Pregunta

Por curiosidad, ¿por qué la función de comparación para stl :: sort no puede ser un miembro estático?

Tengo un pequeño foo de clase auxiliar que se declara y define en un encabezado, pero ahora tengo que crear un archivo foo.cpp para la implementación de cmp () para que no se defina de forma múltiple.

También tengo que pensar en un nombre adecuadamente decorado para que fooCmp () no choque con ningún otro cmp ().

Debido a que no tiene acceso a ninguna variable miembro, cualquier operación de comparación que necesite acceso a algún otro valor (por ejemplo, ordenar por distancia desde foo.bar) necesita la compleja llamada bind2nd call.

¿Fue útil?

Solución

No estoy seguro de qué se queja:

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

Entonces el orden puede ser:

  • Una función
  • Una función miembro estática
  • O un objeto que se comporta como una función.

Lo siguiente funciona para mí:

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);
}

Pero si la clase tiene un orden natural, ¿por qué no simplemente definir el operador < para la clase. Esto le permitirá el acceso a los miembros y se comportará bien para la mayoría de los contenedores / algoritmos estándar que necesitan definir un pedido.

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

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

Otros consejos

Si le preocupa una función de comparación definida de forma múltiple, intente declarar la función con un enlace static. Entonces, el alcance de la función no se extiende más allá de la unidad de compilación donde se encuentra.

Dicho esto, su comparación " function " no es necesario que sea una función, sino que puede ser una función objeto . Un objeto de función es muy parecido a una función pero se implementa como un operator() que toma los parámetros apropiados dentro de una clase regular. Como es una clase regular, puede pasar parámetros de constructor a la clase.

Aquí hay un ejemplo simple:

#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;
}

en realidad suena como si la función fuera declarado en la clase, definido en el encabezado pero fuera de la clase sin vinculación en línea

es decir, algo como:

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

en lugar de

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

el primero de los cuales hará que la función se defina en cada unidad de compilación que

#includes "foo.h"
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top