192 votes

Utilisation du comparateur std : :set personnalisé

J'essaie 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++ :

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'

Qu'est-ce que je fais de mal ?

185voto

Yacoby Points 29771

Vous utilisez une fonction où comme vous devriez utiliser un functor (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 la classe comme paramètre de type

set<int64_t, lex_compare> s;

Si vous voulez éviter le code de la chaudière du functor, vous pouvez également utiliser un pointeur de fonction (en supposant que lex_compare est une fonction).

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

18voto

Potatoswatter Points 70305

La réponse de Yacoby m'inspire à écrire un adaptateur pour encapsuler la chaudière du 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!

Wow, je pense que ça valait le coup !

9voto

Tom Whittock Points 2524

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

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

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

ce qui est irritant de 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 les ensembles avec le même comparateur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X