Różnice między wybraną wersją a wersją aktualną.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
|
lambda [2008/04/16 22:19] przemo86 |
lambda [2008/04/16 23:27] (aktualna) przemo86 |
||
|---|---|---|---|
| Linia 18: | Linia 18: | ||
| ===== Przykłady ===== | ===== Przykłady ===== | ||
| Poniższe przykłady pokazują (w niewielkim stopniu) możliwości tych wyrażeń. Należy w tym miejscu zwrócić uwagę, że często wyrażenia lambda wykorzystują mechanizmy pomocnicze zdefiniowane w innych bibliotekach których nagłówki należy dołączyć. Standardowo dołączamy bibliotekę boost\lambda\lambda.hpp. W przykładach będą pokazane nagłówki które dodatkowo należy dołączyć by kod się skompilował. | Poniższe przykłady pokazują (w niewielkim stopniu) możliwości tych wyrażeń. Należy w tym miejscu zwrócić uwagę, że często wyrażenia lambda wykorzystują mechanizmy pomocnicze zdefiniowane w innych bibliotekach których nagłówki należy dołączyć. Standardowo dołączamy bibliotekę boost\lambda\lambda.hpp. W przykładach będą pokazane nagłówki które dodatkowo należy dołączyć by kod się skompilował. | ||
| + | |||
| ==== Pierwszy rzut oka na boost::lambda ==== | ==== Pierwszy rzut oka na boost::lambda ==== | ||
| Linia 34: | Linia 35: | ||
| </code> | </code> | ||
| - | Kod ten możemy odczytać jako: Wywołaj w tym konkretnym miejscu funkcję którą wyprowadzi na standardowe wyjście argumenty w kolejności 2,1,3. | + | Kod ten możemy odczytać jako: Wywołaj w tym konkretnym miejscu funkcję która wyprowadzi na standardowe wyjście argumenty w kolejności 2,1,3. |
| ==== Elementy kontenerów ==== | ==== Elementy kontenerów ==== | ||
| Linia 50: | Linia 52: | ||
| void funkcja_klasy (const float i) const | void funkcja_klasy (const float i) const | ||
| { | { | ||
| - | std::cout << "\nvoid example::funkcja_klasy : " << i; | + | std::cout << "\nvoid Example::funkcja_klasy : " << i; |
| } | } | ||
| Linia 132: | Linia 134: | ||
| </code> | </code> | ||
| + | |||
| + | |||
| + | |||
| ==== Konstrukcje sterujące oraz pętle ==== | ==== Konstrukcje sterujące oraz pętle ==== | ||
| Linia 145: | Linia 150: | ||
| using namespace Boost::lambda; | using namespace Boost::lambda; | ||
| - | std::cout << "\nPrzyklad 3a.\nUzycie konstrukcji if_else_then(warunek, instrukcje_dla_true, instrukcje_dla_false)." | + | std::cout << "Uzycie konstrukcji if_else_then(warunek, instrukcje_dla_true, instrukcje_dla_false)." |
| - | << " Alternatywnie if_(warunek)[instrukcje_dla_true].else_[instrukcje_dla_false].\n"; | + | << "Alternatywnie if_(warunek)[instrukcje_dla_true].else_[instrukcje_dla_false].\n"; |
| for_each(vec_test.begin(), vec_test.end(), | for_each(vec_test.begin(), vec_test.end(), | ||
| Linia 153: | Linia 158: | ||
| std::cout << constant("\n(if_then_else) Liczba : ") << _1 << constant( " jest mniejsza lub rowna 3!\n"))); | std::cout << constant("\n(if_then_else) Liczba : ") << _1 << constant( " jest mniejsza lub rowna 3!\n"))); | ||
| </code> | </code> | ||
| + | |||
| + | === Switch === | ||
| + | |||
| + | <code cpp> | ||
| + | #include <boost/lambda/lambda.hpp> | ||
| + | #include <boost/lambda/switch.hpp> | ||
| + | |||
| + | using namespace Boost::lambda; | ||
| + | |||
| + | std::cout << "Uzycie konstrukcji switch.\n" ; | ||
| + | (switch_statement( | ||
| + | _1, | ||
| + | case_statement<0> | ||
| + | (std::cout << constant("Wybrales 0 \n")), | ||
| + | case_statement<1> | ||
| + | (std::cout << constant("Wybrales 1 \n")), | ||
| + | default_statement | ||
| + | (std::cout << constant("Nie mam pojecia co wybrales!\n"))) | ||
| + | ) ((make_const(666))); | ||
| + | |||
| + | </code> | ||
| + | |||
| + | Użycie (make_const(666)) jest konieczne. Szablon tej funkcji jest następujący i jest zdefiniowany w bibliotece boost: | ||
| + | <code cpp> | ||
| + | template <class T> inline const T& make_const(const T& t) { return t; } | ||
| + | </code> | ||
| + | Przekazanie samego 666 mogłoby sprowokować błąd ponieważ 666 jest typu int i nie może mieć kwalifikatora const. Szablon natomiast potrzebuje const &. | ||
| + | |||
| + | === Petla while === | ||
| + | |||
| + | <code cpp> | ||
| + | #include <boost/lambda/lambda.hpp> | ||
| + | #include <boost/lambda/loops.hpp> | ||
| + | |||
| + | using namespace Boost::lambda; | ||
| + | |||
| + | std::cout << "Uzycie konstrukcji (while_loop(warunek, instrukcje))(argumenty)\n\n"; | ||
| + | |||
| + | int start = 5; | ||
| + | int end = 10; | ||
| + | (while_loop(_1 <= _2, | ||
| + | (++_1, std::cout << _2 << constant(" - ") << _1 << constant(" = ") << _2 -_1 << constant("\n") ))) | ||
| + | (start,end); | ||
| + | |||
| + | </code> | ||
| + | |||
| + | === Petla do while === | ||
| + | |||
| + | <code cpp> | ||
| + | #include <boost/lambda/lambda.hpp> | ||
| + | #include <boost/lambda/loops.hpp> | ||
| + | |||
| + | using namespace Boost::lambda; | ||
| + | |||
| + | |||
| + | (do_while_loop( _1 == 0 , std::cout << constant ("Uzycie konstrukcji (do_while_loop(warunek, instrukcje))(argumenty).\n")))(make_const(1)); | ||
| + | |||
| + | (do_[ | ||
| + | _1 == 0 , std::cout << constant ("Uzycie konstrukcji (do_[instrukcje].while_(warunek))(argumenty).\n") | ||
| + | ].while_(_1 == 0))(make_const(1)); | ||
| + | </code> | ||
| + | |||
| + | |||
| + | === Petla for === | ||
| + | |||
| + | <code cpp> | ||
| + | #include <boost/lambda/lambda.hpp> | ||
| + | #include <boost/lambda/loops.hpp> | ||
| + | |||
| + | using namespace Boost::lambda; | ||
| + | |||
| + | std::cout << "Uzycie konstrukcji (for_ (war_poczatkowe,warunek, instrukcja iteracji)[instrukcje])(argumenty) : \n"; | ||
| + | int i = 0; | ||
| + | |||
| + | (for_ (var(i)=0 , var(i) < _1, ++var(i)) | ||
| + | [ | ||
| + | var(std::cout) << var(i) << constant("^2 = ") << make_const( var(i)*var(i) ) << constant("\n") | ||
| + | ] | ||
| + | )(make_const (4)); | ||
| + | </code> | ||
| + | |||
| + | Ponieważ powyższe wyrażenie jest wyrażeniem lambda więc aby ono zrozumiało zmienne zewnętrzne należy je stworzyć jego elementem. Taką konwersje tworzy funkcja var(). | ||
| + | |||
| + | |||
| + | ==== Rzutowanie i wyjątki ==== | ||
| + | Biblioteka boost::lambda umożliwia wprowadzenie rzutowania w wyrażeniu lambda jak również genrowanie i przechwytywanie wyjątków. Oto przykład prezentujący konstrukcję: | ||
| + | |||
| + | <code cpp> | ||
| + | #include <boost/lambda/lambda.hpp> | ||
| + | #include <boost/lambda/casts.hpp> | ||
| + | #include <boost/lambda/exceptions.hpp> | ||
| + | |||
| + | struct ExampleDerived : public Example | ||
| + | { | ||
| + | void funkcja_klasy_pochodnej (float i) const | ||
| + | { | ||
| + | std::cout << "void ExampleDerived::funkcja_klasy_pochodnej : " << i << std::endl; | ||
| + | } | ||
| + | }; | ||
| + | |||
| + | using namespace Boost::lambda; | ||
| + | |||
| + | ExampleDerived ex_derv; | ||
| + | |||
| + | // Rzutowanie w tym przykładzie nie powiedzie się i zostanie wygenerowany wyjątek, a następnie | ||
| + | // przechwycony i obsłużony. | ||
| + | |||
| + | std::cout << "Uzycie rzutowania i wykorzystanie mechanizmu wyjatkow w wyrazeniach lambda.\n"; | ||
| + | (try_catch( | ||
| + | bind(&example_derived::funkcja_klasy_pochodnej, ll_dynamic_cast<example_derived&>(*_1),_2), | ||
| + | catch_exception<std::bad_cast>(bind(&example::funkcja_klasy,_1,_2))))(ex_ptr, make_const(66.6f)); | ||
| + | |||
| + | std::cout << std::endl; | ||
| + | // Rzutowanie w tym przykładzie powiedzie się. Przedstawiono dodatkowo schemat zapisu przechwytywania | ||
| + | // wyjątków różnych typów oraz dowolonego wyjątku. | ||
| + | |||
| + | (try_catch( | ||
| + | bind(&example_derived::funkcja_klasy_pochodnej, ll_dynamic_cast<example_derived&>(*_1),_2), | ||
| + | catch_exception<std::bad_cast>(bind(&example::funkcja_klasy,_1,_2)), | ||
| + | catch_exception<std::exception>(), | ||
| + | catch_all()))(make_const(&ex_derv), make_const(77.7f)); | ||
| + | |||
| + | </code> | ||
| + | ===== Zakończenie i plik z przykładami ===== | ||
| + | Wyrażenia lambda to przydatne konstrukcje które nie raz mogą zaoszczędzić czas, zmniejszyć ilość kodu czy zajętą przez program pamięć. Mankamentem jest składnia wyrażeń której należy się po prostu nauczyć i przećwiczyć na wielu przykładach. | ||
| + | |||
| + | Powyższe przykłady można wypróbować pobierając plik: | ||
| + | {{boost_lambda.cpp|}} | ||