Comment trier avec un lambda?

138
sort(mMyClassVector.begin(), mMyClassVector.end(), 
    [](const MyClass & a, const MyClass & b)
{ 
    return a.mProperty > b.mProperty; 
});

Je voudrais utiliser une fonction lambda pour trier les classes personnalisées au lieu de lier une méthode d'instance. Cependant, le code ci-dessus génère l'erreur:

erreur C2564: 'const char *': une conversion de style fonction en type intégré ne peut prendre qu'un seul argument

Cela fonctionne bien avec boost::bind(&MyApp::myMethod, this, _1, _2).

BTR
la source
Le vecteur est d'une structure qui contient un entier et deux chaînes. La propriété ici serait un entier.
BTR
4
Montrez-nous un petit exemple compilable .
GManNickG

Réponses:

159

Je l'ai.

sort(mMyClassVector.begin(), mMyClassVector.end(), 
    [](const MyClass & a, const MyClass & b) -> bool
{ 
    return a.mProperty > b.mProperty; 
});

J'ai supposé qu'il comprendrait que l'opérateur> retournait un booléen (par documentation). Mais apparemment ce n'est pas le cas.

BTR
la source
39
Quelle merde operator>, alors.
GManNickG
2
Ce que vous avez écrit jusqu'à présent n'a guère de sens. Si mProperty est supposé être un int, il a.mProperty>b.mPropertyproduira définitivement un booléen.
sellibitze
1
Alors vous comprenez ma confusion. Je pense que cela pourrait être quelque chose de bizarre avec mon VC10 Express (pas de service pack). J'ai déplacé le projet sur une machine avec Visual Studio 2010 Team et cela a fonctionné sans le "-> bool".
BTR
8
Ne devrait-il pas l'être operator<, non operator>?
Warpspace du
8
Oui, cela devrait être <, pour l'ordre croissant standard. J'ai édité la réponse pour qu'il soit clair que c'était un tri décroissant mais apparemment ma modification n'a pas été utile et a été effacée!
pancake
19

Trop de code, vous pouvez l'utiliser comme ceci:

#include<array>
#include<functional>

int main()
{
    std::array<int, 10> vec = { 1,2,3,4,5,6,7,8,9 };

    std::sort(std::begin(vec), 
              std::end(vec), 
              [](int a, int b) {return a > b; });

    for (auto item : vec)
      std::cout << item << " ";

    return 0;
}

Remplacez "vec" par votre classe et c'est tout.

Adrian
la source
En quoi votre réponse est-elle différente de BTR? Btw. vous pouvez utiliser std :: begin (vec) et std :: end (vec) pour le rendre plus c ++ 11.
Logman
Désolé, je ne sais pas comment j'ai raté ça. Mes yeux s'arrêtent au poste de Stephan. Mon mauvais. (Je modifie le message après vos suggestions)
Adrian
5

Le problème peut-il provenir de la ligne "a.mProperty> b.mProperty"? J'ai obtenu le code suivant pour fonctionner:

#include <algorithm>
#include <vector>
#include <iterator>
#include <iostream>
#include <sstream>

struct Foo
{
    Foo() : _i(0) {};

    int _i;

    friend std::ostream& operator<<(std::ostream& os, const Foo& f)
    {
        os << f._i;
        return os;
    };
};

typedef std::vector<Foo> VectorT;

std::string toString(const VectorT& v)
{
    std::stringstream ss;
    std::copy(v.begin(), v.end(), std::ostream_iterator<Foo>(ss, ", "));
    return ss.str();
};

int main()
{

    VectorT v(10);
    std::for_each(v.begin(), v.end(),
            [](Foo& f)
            {
                f._i = rand() % 100;
            });

    std::cout << "before sort: " << toString(v) << "\n";

    sort(v.begin(), v.end(),
            [](const Foo& a, const Foo& b)
            {
                return a._i > b._i;
            });

    std::cout << "after sort:  " << toString(v) << "\n";
    return 1;
};

La sortie est:

before sort: 83, 86, 77, 15, 93, 35, 86, 92, 49, 21,
after sort:  93, 92, 86, 86, 83, 77, 49, 35, 21, 15,
Stéphan
la source
Ouais, quelque chose de louche avec la configuration sur laquelle j'étais. Compiler sur mon ordinateur portable sans cela très bien sur l'édition Team de Visual Studio 2010. Ce qui m'a indiqué dans ce que je suis retourné pour lier et l'erreur ne disparaîtrait pas. J'étais sur VC10 Express. Punaise?
BTR