Funkcje lambda C++0x w roli predykatów

tech • 325 słów • 2 minuty czytania

Wspominałem nie tak dawno o predykatach szablonowych przy wyszukiwaniu elementów w STL-owych kontenerach za pomocą funkcji find_if. Przedstawiłem tam kilka sposób wykorzystania tego algorytmu i prosty funktorów na bazie biblioteki STL i boost. Dzięki nadchodzącemu wielkimi krokami nowemu standardowi C++0x, tworzenie prostych predykatów stanie się wkrótce jeszcze prostsze dzięki funkcjom i wyrażeniom lambda.

Nie trzeba będzie już pisać prostych funktorów, które nieraz nie mogły znajdować się w pobliżu wykorzystania, przez niemożliwość zdefiniowania szablonowej klasy wewnątrz funkcji lub metody, przez co trochę uciążliwe było ich używanie. A definiowanie ich w oddalonych miejscach kodu nieraz sprawiało trudności w szybkim zrozumieniu kodu i zaburzało przepływ kodu oraz logiki działania.

Na szczęście dzięki wprowadzanym funkcjom i wyrażeniom lambda, będzie można w miejscu wywołania zdefiniować całą kwintesencję działania predykatu, co dla prostych działań będzie bardziej użyteczne, no i powstanie czytelniejszy kod.

Wszelkie poniższe przykłady będą wykorzystywać struktury zdefiniowanej w tamtej notce o predykatach.

Wyszukiwanie elementu w kontenerze z zastosowaniem postaci funkcyjnej lambda wyglądałoby tak:

MyObjVector::iterator it = std::find_if(my_vector.begin(), my_vector.end(),
	[] (const MyObjVector::value_type& obj) -> bool { return obj.name == "foo"; } );

Wydaje się nieco rozległe, ale można użyć prostszej formy w postaci wyrażenia lambda:

MyObjVector::iterator it = std::find_if(my_vector.begin(), my_vector.end(),
	[] (const MyObjVector::value_type& obj) (obj.name == "foo") );

Choć nie jestem pewien do końca czy jest to poprawne, aczkolwiek typ zwracany przez funkcję lambda jest typem wyrażenia. Postać wyrażeniowa jest użyteczna przy prostych operacjach, ale jest ograniczona do pojedynczego wyrażenia.

Może nieco lepszym rozwiązaniem byłoby dorzucić do struktury MyObj operator porównania z std::string lub dedykowaną metodę inline dokonującą takiego porównania:

bool HasName(const std::string& str) const {
	return name == str;
}

I zastosowanie tej metody w wyrażeniu lambda:

[] (const MyObj& obj) (obj.HasName("foo"));

Jak widać lambda będzie zbawieniem w niektórych zastosowaniach i niektórzy nie mogą się już doczekać ;)

Kilka prostych przykładów wykorzystania nowych możliwości języka C++, w tym lambda, można znaleźć w ostatniej notce na “Visual C++ Team Blog”: Lambdas, auto, and static_assert: C++0x Features in VC10, Part 1.

Komentarze (0)

Dodaj komentarz

/dozwolony markdown/

/nie zostanie opublikowany/