2010-04-12 6 views
62

Je suis en train de changer l'ordre par défaut des éléments dans un ensemble d'entiers pour être lexicographique au lieu de numérique, et je ne peux pas obtenir ce qui suit pour compiler avec g ++:En utilisant std personnalisé :: comparateur mis

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

Je reçois l'erreur suivante:

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’ 

ce que je fais mal?

Répondre

107

Vous utilisez une fonction où vous devriez utiliser un foncteur (une classe qui surcharge l'opérateur() pour qu'il puisse être appelé comme une fonction).

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

Vous utilisez ensuite le nom de classe comme paramètre de type

set<int64_t, lex_compare> s; 

Si vous voulez éviter le code foncteur boilerplate vous pouvez également utiliser un pointeur de fonction (en supposant lex_compare est une fonction).

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

fait mon problème semblait être une fermeture supplémentaire> dans la déclaration de l'ensemble. Je ferme la question en tant que faux. (en utilisant une fonction droite au lieu d'un foncteur est parfaitement acceptable pour STL) –

+0

le code dans la question est plus simple que ce que vous avez proposé (pour un comparateur de fonction simple) et fonctionne très bien. –

+4

@Omry: Je serais intéressé de savoir quel compilateur vous utilisez: http://codepad.org/IprafuVf –

14

La réponse de Yacoby m'inspire pour écrire un adaptateur pour encapsuler la plaquette du foncteur.

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! 

Wow, je pense que ça en valait la peine!

+9

Une question d'opinion, je suppose. –

4

Vous pouvez utiliser un comparateur de fonction sans l'emballer comme ceci:

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

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

qui est irritant pour taper à chaque fois que vous avez besoin d'un ensemble de ce type, et peut causer des problèmes si vous ne créez pas tous ensembles avec le même comparateur.

7

solution 11 C++ avec lambda et sans struct ou fonction:

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

Ideone

+0

type de retour pour lambda? – user501138

+0

@ user501138, true si 'a diraria

Questions connexes