Narzędzia użytkownika

Narzędzia witryny


bind

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
bind [2008/04/14 08:50]
maciejp
bind [2008/04/14 09:00] (aktualna)
maciejp
Linia 43: Linia 43:
 Realizujemy to za pomocą symbli zastępczych oznaczanych jako ''​_1'',​ ''​_2'',​ ..., ''​_9''​. Dostępnych mamy łacznie 9 takich symboli. Ogranicza to możliwośc tworzenia funktorów do funktorów 9 elementowych (w przypadku funkcji składowych jest to 8 argumentów;​ musimy pamietć o przekazaniu obiektu na rzecz, którego będzie wywoływany funktor). Symbol ''​_1''​ oznacza "​zastąp przez pierwszy argument wejściowy",​ analogicznie pozostałe osiem. Realizujemy to za pomocą symbli zastępczych oznaczanych jako ''​_1'',​ ''​_2'',​ ..., ''​_9''​. Dostępnych mamy łacznie 9 takich symboli. Ogranicza to możliwośc tworzenia funktorów do funktorów 9 elementowych (w przypadku funkcji składowych jest to 8 argumentów;​ musimy pamietć o przekazaniu obiektu na rzecz, którego będzie wywoływany funktor). Symbol ''​_1''​ oznacza "​zastąp przez pierwszy argument wejściowy",​ analogicznie pozostałe osiem.
 Argumenty można dowolnie zamieniać ze stałymi jak i zamieniać ich kolejność. Argumenty można dowolnie zamieniać ze stałymi jak i zamieniać ich kolejność.
 +
  
  
 =====Użycie z funktorami===== =====Użycie z funktorami=====
  
-boost::bind nie jest ograniczony tylko do wskaźników do funkcji, akceptuje min. również funktory. W przypadku użycia funktora zazwyczaj należy jawnie podać typ zwracany przez operator() funktora (ewentualnie zdefinjować typ result_type w funktorze).+''​boost::bind'' ​nie jest ograniczony tylko do wskaźników do funkcji, akceptuje min. również funktory. W przypadku użycia funktora zazwyczaj należy jawnie podać typ zwracany przez ''​operator()'' ​funktora (ewentualnie zdefinjować typ ''​result_type'' ​w funktorze).
  
 <code cpp> <code cpp>
Linia 63: Linia 64:
 </​code>​ </​code>​
  
-Niektóre kompilatory mają problem ze składnią w postaci bind<​R>​(...). Wyrażenie to można zastąpić postacią alternatwną.+Niektóre kompilatory mają problem ze składnią w postaci ​''​bind<​R>​(...)''​. Wyrażenie to można zastąpić postacią alternatwną.
  
 <code cpp> <code cpp>
 boost::​bind(boost::​type<​int>​(),​ f, _1, _1)(x); boost::​bind(boost::​type<​int>​(),​ f, _1, _1)(x);
 </​code>​ </​code>​
 +
  
  
Linia 74: Linia 76:
 =====Użycie ze wskaźnikami do składowych===== =====Użycie ze wskaźnikami do składowych=====
  
-Wskaźniki do metod i danych sładowych nie są obiektami funkcyjnymi,​ ponieważ nie wspierają operatora operator(). Dla wygody boost::bind akceptuje te wskażniki jako pierwszy argument. boost::bind używa funkcji boost::​mem_fn do konwersji wskźników do składowych na funktory. Innymi słowami, wyrażenie:+Wskaźniki do metod i danych sładowych nie są obiektami funkcyjnymi,​ ponieważ nie wspierają operatora ​''​operator()''​. Dla wygody ​''​boost::bind'' ​akceptuje te wskażniki jako pierwszy argument. ​''​boost::bind'' ​używa funkcji ​''​boost::​mem_fn'' ​do konwersji wskźników do składowych na funktory. Innymi słowami, wyrażenie:
  
 <code cpp> <code cpp>
Linia 86: Linia 88:
 </​code>​ </​code>​
  
-gdzie R jest typem zwracanym przez Foo::f w przypadku metod lub typem danych w przypadku danych składowych.+gdzie ''​R'' ​jest typem zwracanym przez ''​Foo::f'' ​w przypadku metod lub typem danych w przypadku danych składowych.
  
 Przykład: Przykład:
Linia 106: Linia 108:
 </​code>​ </​code>​
  
-Jako drugi argument boost::bind przekazujemy obiekt klasy na rzecz, której ma być wywoływana funkcja (jest to oczywiste, jeśli zauważymy, że pierwszym niejawnym argumentem metod jest zawsze wskaźnik this - adres obiektu). Najciekawsze są dwie ostatnie linijki przykładu. ''​bind(&​Foo::​f,​ x, _1)''​ przechowuje wewnętrzną kopję obieku ''​x''​ (warto zwrócić na to uwagę, szczególnie gdy kopjowanie obiektu jest kosztowne), natomiast ''​bind(&​Foo::​f,​ p, _1)''​ kopję wskażnika ''​p''​ (''​p''​ jest sprytnym wskaźnikiem ''​shared_ptr<>''​),​ tworzony obiekt funkcyjny przechowuje swoją referencję do instancji klasy Foo i będzie ona poprawna nawet kiedy p wyjdzie poza zasięg lub wykonamy na ''​p reset()''​.+Jako drugi argument ​''​boost::bind'' ​przekazujemy obiekt klasy na rzecz, której ma być wywoływana funkcja (jest to oczywiste, jeśli zauważymy, że pierwszym niejawnym argumentem metod jest zawsze wskaźnik this - adres obiektu). Najciekawsze są dwie ostatnie linijki przykładu. ''​bind(&​Foo::​f,​ x, _1)''​ przechowuje wewnętrzną kopję obieku ''​x''​ (warto zwrócić na to uwagę, szczególnie gdy kopjowanie obiektu jest kosztowne), natomiast ''​bind(&​Foo::​f,​ p, _1)''​ kopję wskażnika ''​p''​ (''​p''​ jest sprytnym wskaźnikiem ''​shared_ptr<>''​),​ tworzony obiekt funkcyjny przechowuje swoją referencję do instancji klasy Foo i będzie ona poprawna nawet kiedy p wyjdzie poza zasięg lub wykonamy na ''​p reset()''​.
  
 Funcję ''​boost::​bind''​ można też bezprolemowo użyć z funkcjami wirtualnymi. Funcję ''​boost::​bind''​ można też bezprolemowo użyć z funkcjami wirtualnymi.
Linia 146: Linia 148:
 derived! derived!
 </​code>​ </​code>​
 +
  
  
 =====Użycie zagnieżdżeń do kompozycji fukcji===== =====Użycie zagnieżdżeń do kompozycji fukcji=====
  
-Część argumentów przekazywanych bind może być zagnieżdżonymi wyrażeniami boost::​bind.+Część argumentów przekazywanych bind może być zagnieżdżonymi wyrażeniami ​''​boost::bind''​.
  
 <code cpp> <code cpp>
Linia 156: Linia 159:
 </​code>​ </​code>​
  
-Wewnętrzne wyrażenia są ewaluowane w bliżej nie okreśłonej kolejności,​ ale przed wywołaniem funktora zewnętzrnego boost::​bind. Odnosząc się do przykładu, kiedy utworzony funktor jest wywoływany z argumentem x, w pierwszej kolejności ewalowany jest bind(g, _1)(x), dając g(x), następnie bind(f, g(x))(x), dając finalny wynik w postaci wywołania f(g(x)).+Wewnętrzne wyrażenia są ewaluowane w bliżej nie okreśłonej kolejności,​ ale przed wywołaniem funktora zewnętzrnego ​''​boost::bind''​. Odnosząc się do przykładu, kiedy utworzony funktor jest wywoływany z argumentem ​''​x''​, w pierwszej kolejności ewalowany jest ''​bind(g, _1)(x)''​, dając ​''​g(x)''​, następnie ​''​bind(f, g(x))(x)''​, dając finalny wynik w postaci wywołania ​''​f(g(x))''​.
  
-Ta cecha boost::bind może być bardzo dobrze zastosowana do kompozycji funkcji.+Ta cecha ''​boost::bind'' ​może być bardzo dobrze zastosowana do kompozycji funkcji.
  
-Trzeba zaznaczyć, że pierwszy argument boost::bind (opakowywany obiekt funkcyjny) nie jest ewalowany, nawet wtedy, kiedy jest to obiekt funkcyjny produkowany przez zagnieżdżone wywołanie bind lub argument w postaci ​ symbola zastępczego. Poniższy przykład nie będzie działał tak, jakbyśmy tego oczekiwali.+Trzeba zaznaczyć, że pierwszy argument ​''​boost::bind'' ​(opakowywany obiekt funkcyjny) nie jest ewalowany, nawet wtedy, kiedy jest to obiekt funkcyjny produkowany przez zagnieżdżone wywołanie ​''​bind'' ​lub argument w postaci ​ symbola zastępczego. Poniższy przykład nie będzie działał tak, jakbyśmy tego oczekiwali.
  
 <code cpp> <code cpp>
Linia 170: Linia 173:
 </​code>​ </​code>​
  
-Oczekiwany efekt uzyskamy korzystając z pomocniczego obiektu funkcyjnego apply (implementacja apply w boost/​bind/​apply.hpp),​ który podajemy jako pierwszy argument boost::​bind. Poprzedni przykład powinien wyglądać następująco.+Oczekiwany efekt uzyskamy korzystając z pomocniczego obiektu funkcyjnego ​''​apply'' ​(implementacja ​''​apply'' ​''​boost/​bind/​apply.hpp''​), który podajemy jako pierwszy argument ​''​boost::bind''​. Poprzedni przykład powinien wyglądać następująco.
  
 <code cpp> <code cpp>
Linia 180: Linia 183:
 </​code>​ </​code>​
  
-Używając bind można komponować funkcje korzystając naraz z boost::bind i funkcji (algorytmów) z biblioteki standardowej.+Używając ​''​bind'' ​można komponować funkcje korzystając naraz z ''​boost::bind'' ​i funkcji (algorytmów) z biblioteki standardowej.
  
 <code cpp> <code cpp>
Linia 212: Linia 215:
 </​code>​ </​code>​
  
-Jak widać na przykładzie łatwo można tworzyć złożone predykaty. Często trzeba się jednak często zastanowić,​ czy stosować bardzo złożone wyrażenia. Utrudniają one późniejszą analizę kodu, często wręcz uniemożliwiają. Warto rozważyć w takich przypadkach zdefinjowanie funktora lub operatora operator() dla klasy.+Jak widać na przykładzie łatwo można tworzyć złożone predykaty. Często trzeba się jednak często zastanowić,​ czy stosować bardzo złożone wyrażenia. Utrudniają one późniejszą analizę kodu, często wręcz uniemożliwiają. Warto rozważyć w takich przypadkach zdefinjowanie funktora lub operatora ​''​operator()'' ​dla klasy. 
  
 =====Użycie z biblioteką Boost.Function===== =====Użycie z biblioteką Boost.Function=====
  
-Funktor zwracany przez boost::bind można przypisać do obiektu funkcyjnego boos::​function. W ten sposób można między innymi przechowywć wcześniej utworzone fukntory jako zmienne i pola klasy albo przekazywać je jako argument do konstruktorów lub funkcji. Przypisania możemy dokonać wykłym operatorem =.+Funktor zwracany przez ''​boost::bind'' ​można przypisać do obiektu funkcyjnego ​''​boos::​function''​. W ten sposób można między innymi przechowywć wcześniej utworzone fukntory jako zmienne i pola klasy albo przekazywać je jako argument do konstruktorów lub funkcji. Przypisania możemy dokonać wykłym operatorem ​''​=''​.
  
 <code cpp> <code cpp>
Linia 224: Linia 228:
 </​code>​ </​code>​
  
-Warunkiem poprawnej kompilacji jest dokładne określenie typu szablonu obiektu function (zasada działania boost::​function wykracza poza ten artykuł).+Warunkiem poprawnej kompilacji jest dokładne określenie typu szablonu obiektu function (zasada działania ​''​boost::​function'' ​wykracza poza ten artykuł). 
  
 =====Przeciążone operatory===== =====Przeciążone operatory=====
  
-Przeciązone operatory dla boost::bind pojawiły się w Boost 1.33+Przeciązone operatory dla ''​boost::bind'' ​pojawiły się w Boost 1.33
  
-Obiekty funkcyjne produkowane przez boost::bind przeciążają logiczny operator przecenia ! oraz operatory relacji ==, !=, <, <=, >, >=.+Obiekty funkcyjne produkowane przez ''​boost::bind'' ​przeciążają logiczny operator przecenia ​''​!'' ​oraz operatory relacji ​''​==''​''​!=''​''​<''​''​<=''​''​>''​''​>=''​.
  
 <​code>​ <​code>​
Linia 242: Linia 247:
 </​code>​ </​code>​
  
-gdzie logical_not jest funktorem przyjmującym jeden argument x i zwracający !x.+gdzie ''​logical_not'' ​jest funktorem przyjmującym jeden argument ​''​x'' ​i zwracający ​''​!x''​.
  
 <code cpp> <code cpp>
 bind(f, ...) op x bind(f, ...) op x
 </​code>​ </​code>​
-op jest operatorem relacji, wyrażniu temu odpowiada+''​op'' ​jest operatorem relacji, wyrażniu temu odpowiada
  
 <code cpp> <code cpp>
 bind(relation(),​ bind(f, ...), x) bind(relation(),​ bind(f, ...), x)
 </​code>​ </​code>​
-gdzie relation jest funktorem przyjmującym dwa argumenty a i b zwracającym a op b.+gdzie ''​relation'' ​jest funktorem przyjmującym dwa argumenty ​''​a'' ​''​b''​ oraz zwracającym ​''​a op b''​.
  
-Przeciążenie tych operatorów umożliwia na konwencjonalne negowanie wyniku boost::​bind:​+Przeciążenie tych operatorów umożliwia na konwencjonalne negowanie wyniku ​''​boost::bind''​:
  
 <code cpp> <code cpp>
Linia 260: Linia 265:
 </​code>​ </​code>​
  
-oraz na porównywanie wyników boost::bind z wartościami:​+oraz na porównywanie wyników ​''​boost::bind'' ​z wartościami:​
  
 <code cpp> <code cpp>
Linia 272: Linia 277:
 </​code>​ </​code>​
  
-albo z innym wyrażeniem boost::​bind:​+albo z innym wyrażeniem ​''​boost::bind''​:
  
 <code cpp> <code cpp>
 std::​sort(first,​ last, bind(&​X::​name,​ _1) < bind(&​X::​name,​ _2)); std::​sort(first,​ last, bind(&​X::​name,​ _1) < bind(&​X::​name,​ _2));
 </​code>​ </​code>​
 +
  
  
Linia 282: Linia 288:
 =====Inny przykład użycia===== =====Inny przykład użycia=====
  
-boost::bind umożliwia w przeciwnieństwie do funkcji z biblioteki standardowej (służących do tworzenia adpterów funkcji) bardzo elastyczną pracę z kodem.+''​boost::bind'' ​umożliwia w przeciwnieństwie do funkcji z biblioteki standardowej (służących do tworzenia adpterów funkcji) bardzo elastyczną pracę z kodem.
  
 <code cpp> <code cpp>
Linia 342: Linia 348:
 </​code>​ </​code>​
  
-Użycie funkcji standardowych (std::​mem_fun_ref i std::​mem_fun) zmusza do zmian także pętli for_each po każdej modyfikacji typu przechowywanego przez wektor, a nawet uniemożliwia dalszą pracę (brak obsługi w przypadku użycia sprytnych wskaźników).+Użycie funkcji standardowych (''​std::​mem_fun_ref'' ​''​std::​mem_fun''​) zmusza do zmian także pętli ​''​for_each'' ​po każdej modyfikacji typu przechowywanego przez wektor, a nawet uniemożliwia dalszą pracę (brak obsługi w przypadku użycia sprytnych wskaźników).\\ 
 +\\ 
 +\\ 
 + --- //​[[mplachta@stud.elka.pw.edu.pl|Maciej Płachta H1ISI]]//
bind.1208155839.txt.gz · ostatnio zmienione: 2008/04/14 08:50 przez maciejp