2012-01-05 18 views
19

Próbuję zaimplementować mapę z funkcji lambda w C++ 11 jako takiejKorzystanie lambdas w mapach

std::map<int, int, [](const int&a, const int& b) { return a < b; }> test; 

ale to się nie uda z

error: type/value mismatch at argument 3 in template parameter list for ‘template<class _Key, class _Tp, class _Compare, class _Alloc> class std::map’

error: expected a type, got ‘{}’

error: invalid type in declaration before ‘;’ token

jakąś radę?

+1

Podałeś lambdę, tj. Obiekt; parametr szablonu musi być typem _, a nie instancją typu. – ildjarn

+0

Zobacz [C++ priority_queue z błędem porównania lambda] (http://stackoverflow.com/questions/5807735/c-priority-queue-with-lambda-comparator-error) i [Czy "typ" wyrażenia lambda może być wyrażone?] (http://stackoverflow.com/questions/3867276/can-the-type-of-a-lambda-expression-be-expressed). –

Odpowiedz

25

Musisz podać typ lambda jako argument szablonu, a nie samą lambdę. Co chcesz to:

auto mycomp = [](const int&a, const int& b) { return a < b; }; 
std::map<int, int, decltype(mycomp)> test(mycomp); 

Chociaż w rzeczywistości, ponieważ Twój lambda nie ma zrzuty, to może faktycznie być przechowywane w wskaźnik do funkcji, tak alternatywnie, można to zrobić:

std::map<int, int, bool(*)(const int&,const int&)> 
    test([](const int&a, const int& b) { return a < b; }); 

Choć Pierwszą o wiele bardziej czytelną. Chociaż korzystanie z funkcji wskaźnik typu jest bardziej wszechstronny. Oznacza to, że może przyjąć dowolny wskaźnik funkcji lub nie przechwytującą lambda, która pasuje do tego podpisu. Ale jeśli zmienisz swoją lambdę do przechwytywania, nie zadziała. Dla bardziej wszechstronny wersji, można użyć std::function, tj:

std::map<int, int, std::function<bool(const int&, const int&)>> 

który będzie działał z każdą funkcją, lambda (przechwytywanie lub nie) lub funkcja obiektu, o ile pasuje podpis.

+0

Zupełnie, panie Lindley. –

+0

Należy zauważyć, że jeśli zadeklarowano 2 mapy, miałyby 2 różne typy i byłyby niezgodne. –

+0

@Jesse: Byłby to jeden z argumentów za używaniem typu wskaźnika funkcji zamiast typu decltype w lambda, tak jak w moim drugim przykładzie. Ale lepiej (dla kompatybilności, nie wydajności) byłoby użycie 'std :: function', to byłoby kompatybilne nawet z lambdami, które przechwytują i innymi obiektami funkcji. –