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
Next revision Both sides next revision
bind [2008/04/12 19:24]
maciejp
bind [2008/04/14 08:50]
maciejp
Linia 1: Linia 1:
 ======Biblioteka Boost.Bind====== ======Biblioteka Boost.Bind======
  
-Funkcja boost::bind jest generalizacją funkcji std::​bind1st i std::​bind2nd dostępnych w bibliotece standardowej. Funkcja ta wspiera funktory, funkcje, wskaźniki do funkcji oraz wskaźniki do funkcji składowych. Jest w stanie związać dowolny argument ze specyficzną wartością albo przekierować argumenty wejściowe we wskazane pozycje. boost::bind nie nakłada żadnych wymagań obiektom funkcyjnym, w ogólności nie wymaga standardowych definicji typów takich jak: result_type,​ first_argument_type,​ second_argument_type. +Funkcja ​''​boost::bind'' ​jest generalizacją funkcji ​''​std::​bind1st'' ​''​std::​bind2nd'' ​dostępnych w bibliotece standardowej. Funkcja ta wspiera funktory, funkcje, wskaźniki do funkcji oraz wskaźniki do funkcji składowych. Jest w stanie związać dowolny argument ze specyficzną wartością albo przekierować argumenty wejściowe we wskazane pozycje. ​''​boost::bind'' ​nie nakłada żadnych wymagań obiektom funkcyjnym, w ogólności nie wymaga standardowych definicji typów takich jak: ''​result_type''​''​first_argument_type''​''​second_argument_type''​
-Do korzystania z funcji boost::bind konieczne jest dołączenie nagłówka ​boost/​bind.hpp. +Do korzystania z funcji boost::bind konieczne jest dołączenie nagłówka ​''​boost/​bind.hpp''​.
- +
  
  
Linia 24: Linia 22:
 </​code>​ </​code>​
  
-Najprostszym przypadkiem użycia boost::bind jest stworzenie bezargumentowego funktora przez zastąpienie argumentów funkcji wartościami stałymi.+Najprostszym przypadkiem użycia ​''​boost::bind'' ​jest stworzenie bezargumentowego funktora przez zastąpienie argumentów funkcji wartościami stałymi.
  
 <code cpp> <code cpp>
Linia 30: Linia 28:
 </​code>​ </​code>​
  
-Jako pierwszy argument boost::bind podajemy wskaźnik do funkcji, następne ​argumenty ​przypisywane są jako pierwszy i drugi argument funkcji g. Typ zwracany przez funktor jest identyczny z typem zwracanym przez funkcję podaną jako pierwszy argument.+Jako pierwszy argument ​''​boost::bind'' ​podajemy wskaźnik do funkcji, następne ​dwa przypisywane są jako pierwszy i drugi argument funkcji ​''​g''​. Typ zwracany przez funktor jest identyczny z typem zwracanym przez funkcję podaną jako pierwszy argument.
 Znacznie ciekawszym mechanizmem jest możliwość selektywnego zastępowania argumentów lub kolejności przekazywanych argumentów. Znacznie ciekawszym mechanizmem jest możliwość selektywnego zastępowania argumentów lub kolejności przekazywanych argumentów.
  
Linia 36: Linia 34:
 int main() { int main() {
   int i1=1,​i2=2,​i3=3,​i4=4,​i5=5,​i6=6,​i7=7,​i8=8,​i9=9;​   int i1=1,​i2=2,​i3=3,​i4=4,​i5=5,​i6=6,​i7=7,​i8=8,​i9=9;​
-  ​(boost::​bind(&​nine_arguments,​_9,​_2,​_1,​_6,​_3,​_8,​_4,​_5,​_7))  ​//​utworzenie tymczasowego funktora i wywołanie +  boost::​bind(f,​_9,​_2,​_1,​_6,​_3,​_8,​_4,​_5,​_7) ​          ​//​utworzenie tymczasowego funktora i wywołanie 
-    (i1,​i2,​i3,​i4,​i5,​i6,​i7,​i8,​i9); ​                           //​odpowiadające wywołaniu f(i9, i2, i1, i6, i3, i8, i4, i5, i7) +    (i1,​i2,​i3,​i4,​i5,​i6,​i7,​i8,​i9); ​                    ​//​odpowiadające wywołaniu f(i9, i2, i1, i6, i3, i8, i4, i5, i7) 
-                                                             ​//w wyniku otrzymamy ciąg: 921638457 +                                                      //w wyniku otrzymamy ciąg: 921638457 
-+  ​return ​0; 
-bind(f, _2, _3, _1, _1, 0, 0, _3, 0, _2)(x, y, z) //​utworzenie tymczasowego funktora i wywołanie +}                                               
-                                                    +
 </​code>​ </​code>​
  
-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. 
-Jak wynika z przykładu, ​można dowolnie ​"​mieszać" argumenty ​ze stałymi jak i 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 funkcji, akceptuje min. również funktory. W przypadku użycia funktora zazwyczaj ​trzeba ​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 70: Linia 68:
 boost::​bind(boost::​type<​int>​(),​ f, _1, _1)(x); boost::​bind(boost::​type<​int>​(),​ f, _1, _1)(x);
 </​code>​ </​code>​
 +
 +
  
  
 =====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 przekonwertowania ​wskźników do składowych na funktory. Innymi słowy, 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 106: Linia 106:
 </​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.
  
 <code cpp> <code cpp>
Linia 131: Linia 131:
   base* bp = &d;   base* bp = &d;
  
-boost::​bind(&​base::​print,​ _1)(b); +  ​boost::​bind(&​base::​print,​ _1)(b); 
-boost::​bind(&​base::​print,​ _1)(bp); +  boost::​bind(&​base::​print,​ _1)(bp); 
-boost::​bind(&​base::​print,​ _1)(d);+  boost::​bind(&​base::​print,​ _1)(d); 
 + 
 +  return 0; 
 +}
 </​code>​ </​code>​
  
Linia 213: Linia 216:
 =====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ęzy innymi przechowywć wcześniej utworzone fukntory ​lub przekazywać je jako argument do konstruktorówfunkcji. 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 222: Linia 225:
  
 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=====
Linia 233: Linia 235:
 !bind(f, ...) !bind(f, ...)
 </​code>​ </​code>​
 +
 Jest ekwiwalentem Jest ekwiwalentem
 +
 <code cpp> <code cpp>
 bind(logical_not(),​ bind(f, ...)) bind(logical_not(),​ bind(f, ...))
 </​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
  
Linia 274: Linia 279:
  
  
-=====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.
Linia 317: Linia 323:
     statuses.end(),​     statuses.end(),​
     boost::​bind(&​status::​report,​ _1));     boost::​bind(&​status::​report,​ _1));
 +
 +  return 0;
 } }
 </​code>​ </​code>​
bind.txt · ostatnio zmienione: 2008/04/14 09:00 przez maciejp