Narzędzia użytkownika

Narzędzia witryny


lambda

Różnice

Różnice między wybraną wersją a wersją aktualną.

Odnośnik do tego porównania

Both sides previous revision Previous revision
Next revision
Previous revision
lambda [2008/04/16 22:21]
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 << " Uzycie 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 157: Linia 162:
  
 <code cpp> <code cpp>
-#include <​algorithm>​ 
 #include <​boost/​lambda/​lambda.hpp>​ #include <​boost/​lambda/​lambda.hpp>​
 #include <​boost/​lambda/​switch.hpp>​ #include <​boost/​lambda/​switch.hpp>​
Linia 163: Linia 167:
         using namespace Boost::​lambda;​         using namespace Boost::​lambda;​
  
- std::cout << "\nPrzyklad 3b.\nUzycie ​konstrukcji switch.\n\n" ​  ;+ std::cout << "Uzycie ​konstrukcji switch.\n" ​  ;
  (switch_statement(  (switch_statement(
  _1,  _1,
  case_statement<​0>​  case_statement<​0>​
-  (var(std::cout<< constant("​Wybrales 0 \n")),+ (std::cout << constant("​Wybrales 0 \n")),
  case_statement<​1>​  case_statement<​1>​
-  (var(std::cout<< constant("​Wybrales 1 \n")),+ (std::cout << constant("​Wybrales 1 \n")),
  default_statement  default_statement
-  (var(std::cout<< constant("​Nie mam pojecia co wybrales!\n"​)))+ (std::cout << constant("​Nie mam pojecia co wybrales!\n"​)))
  ) ((make_const(666)));​  ) ((make_const(666)));​
  
 </​code>​ </​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|}}
lambda.1208377302.txt.gz · ostatnio zmienione: 2008/04/16 22:21 przez przemo86