Como classificar com uma lambda?

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

Gostaria de usar uma função lambda para classificar classes personalizadas no lugar de vincular um método de instância. No entanto, o código acima gera o erro:

erro C2564: 'const char *': uma conversão no estilo de função para um tipo interno pode levar apenas um argumento

Funciona bem com boost::bind(&MyApp::myMethod, this, _1, _2).

BTR
fonte
O vetor é de uma estrutura que contém um número inteiro e duas cadeias. A propriedade aqui seria um número inteiro.
BTR 25/02
4
Mostre-nos um pequeno exemplo compilável .
GManNickG 25/02

Respostas:

157

Entendi.

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

Eu assumi que descobriria que o operador retornou um bool (por documentação). Mas, aparentemente, não é assim.

BTR
fonte
39
Que porcaria operator>, então.
GManNickG 25/02
2
O que você escreveu até agora faz pouco sentido. Se mProperty deve ser um int a.mProperty>b.mProperty, definitivamente produzirá um bool.
sellibitze
1
Então você entende minha confusão. Eu acho que pode ser algo estranho com o meu VC10 Express (sem service pack). Mudei o projeto para uma máquina com o Visual Studio 2010 Team e ele funcionou sem o "-> bool".
BTR 26/02
8
Não deveria ser operator<, não operator>?
Warpspace 11/09/13
8
Sim, deve ser <, para ordem ascendente padrão. Editei a resposta para deixar claro que era do tipo descendente, mas aparentemente minha edição foi inútil e foi apagada!
panqueca
18

Para muito código, você pode usá-lo assim:

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

Substitua "vec" por sua classe e é isso.

Adrian
fonte
Como sua resposta é diferente da BTR? Btw. você pode usar std :: begin (vec) e std :: end (vec) para torná-lo mais c ++ 11.
Logman
Desculpe, não sei como senti falta disso. Meus olhos param no posto de Stephan. My bad (i modificar o cargo após suas sugestões).
Adrian
5

O problema pode estar na linha "a.mProperty> b.mProperty"? Eu consegui o seguinte código para trabalhar:

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

A saída é:

before sort: 83, 86, 77, 15, 93, 35, 86, 92, 49, 21,
after sort:  93, 92, 86, 86, 83, 77, 49, 35, 21, 15,
Stephan
fonte
Sim, algo maluco com a configuração em que eu estava. Compilar no meu laptop sem ele muito bem na edição Team do Visual Studio 2010. O que me deu uma pista do que eu havia ligado novamente e o erro não desapareceu. Eu estava no VC10 Express. Erro?
BTR 26/02