2010-04-12 15 views
62

Estoy tratando de cambiar el orden predeterminado de los elementos de un conjunto de números enteros para ser lexicográfico en lugar de numérica, y no puedo conseguir lo siguiente para compilar con g ++:std :: set encargo comparador

file.cpp:

bool lex_compare(const int64_t &a, const int64_t &b) 
{ 
    stringstream s1,s2; 
    s1 << a; 
    s2 << b; 
    return s1.str() < s2.str(); 
} 

void foo() 
{ 
    set<int64_t, lex_compare> s; 
    s.insert(1); 
    ... 
} 

me sale el siguiente error:

error: type/value mismatch at argument 2 in template parameter list for ‘template<class _Key, class _Compare, class _Alloc> class std::set’ 
error: expected a type, got ‘lex_compare’ 

¿qué estoy haciendo mal?

Respuesta

107

Está utilizando una función en tanto que se debe utilizar un funtor (una clase que sobrecarga la) operador (por lo que se puede llamar como una función).

struct lex_compare { 
    bool operator() (const int64_t& lhs, const int64_t& rhs) const { 
     stringstream s1, s2; 
     s1 << lhs; 
     s2 << rhs; 
     return s1.str() < s2.str(); 
    } 
}; 

a continuación, utiliza el nombre de clase como el parámetro de tipo

set<int64_t, lex_compare> s; 

Si se quiere evitar el código repetitivo funtor también se puede utilizar un puntero de función (suponiendo lex_compare es una función).

set<int64_t, bool(*)(const int64_t& lhs, const int64_t& rhs)> s(&lex_compare); 
+0

en realidad mi problema parecía ser un cierre adicional> en la declaración del conjunto. Estoy cerrando la pregunta como falsa. (usando una función lineal en lugar de un funtor es perfectamente válido para STL) –

+0

el código en la pregunta es más simple de lo que usted propone (para un simple comparador de función) y funciona muy bien. –

+4

@Omry: Yo estaría interesado en saber qué compilador que está utilizando: http://codepad.org/IprafuVf –

14

La respuesta de Yacoby me inspira a escribir un adaptador para encapsular la plantilla del functor.

template< class T, bool (*comp)(T const &, T const &) > 
class set_funcomp { 
    struct ftor { 
     bool operator()(T const &l, T const &r) 
      { return comp(l, r); } 
    }; 
public: 
    typedef std::set< T, ftor > t; 
}; 

// usage 

bool my_comparison(foo const &l, foo const &r); 
set_funcomp< foo, my_comparison >::t boo; // just the way you want it! 

¡Guau, creo que valió la pena!

+9

Una cuestión de opinión, supongo. –

4

Puede utilizar un comparador función sin envolviéndolo así:

bool comparator(const MyType &lhs, const MyType &rhs) 
{ 
    return [...]; 
} 

std::set<MyType, bool(*)(const MyType&, const MyType&)> mySet(&comparator); 

que es irritante para escribir a máquina cada vez que se necesita un conjunto de ese tipo, y puede causar problemas si no se crea todo establece con el mismo comparador.

solución
7

C++ 11 con lambda y sin función o estructura:

auto cmp = [](int a, int b) { return ... }; 
set<int, decltype(cmp)> s(cmp); 

Ideone

+0

tipo de devolución para lambda? – user501138

+0

@ user501138, cierto si un ' diraria

Cuestiones relacionadas