home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 March / Chip_2002-03_cd1.bin / obsahy / Chip_txt / txt / 150-153.txt < prev    next >
Text File  |  2002-02-03  |  17KB  |  261 lines

  1.  
  2. Knihovna STL jazyka C++
  3. Jak se na funktor volß... (2)
  4. JakΘ funktory pro nßs p°ichystali tv∙rci STL a na co si dßt pozor - to vÜe najdete v tomto zßv∞reΦnΘm dφlu naÜeho povφdßnφ o funktorech.
  5.  
  6. Koncepty funkcφ v C++
  7. Ji₧ v p°edminulΘm Φlßnku o STL [3] jsme uvedli, tehdy bez dalÜφho vysv∞tlenφ, hierarchii koncept∙ funkcφ. P°φsluÜnΘ schΘma, pro zm∞nu poΦeÜt∞nΘ, zde pro pohodlφ opakujeme a o celΘ v∞ci si nynφ povφme n∞co vφce. 
  8. Jak u₧ vφme, modelem konceptu v C++ m∙₧e b²t datov² typ. Ale co funkce? M∙₧e b²t obyΦejnß funkce modelem konceptu? Odpov∞∩ znφ: Ano, ale musφme na ni pohlφ₧et jako na typ (ukazatel na funkci). Nap°φklad funkce
  9. bool mensi_nez(int x, int y)
  10.    { return x < y; }
  11. je typu bool (*)(int, int). 
  12. VÜechny funkce majφ jeden nßvratov² typ (t°eba i void), ale mohou se liÜit poΦtem parametr∙. Podle poΦtu parametr∙ d∞lφme funkce na:
  13. * funkce bez parametr∙ - volajφ se bez parametr∙. TakovΘ funkci se takΘ °φkß generßtor, nebo¥ na v²stupu "generuje" n∞jakou hodnotu;
  14. * unßrnφ funkce - volajφ se s jednφm parametrem;
  15. * binßrnφ funkce - volajφ se se dv∞ma parametry;
  16. * obecn∞ n-ßrnφ funkce - volajφ se s n parametry.
  17. Pokud funkce vracφ hodnotu, kterß m∙₧e b²t interpretovßna jako pravdivostnφ, naz²vßme tuto funkci predikßt. Predikßtem samoz°ejm∞ m∙₧e b²t jak unßrnφ, tak binßrnφ funkce (obecn∞ jakßkoli n-ßrnφ funkce); hovo°φme pak o unßrnφm nebo binßrnφm predikßtu (n-ßrnφm predikßtu). Jak je vid∞t ze schΘmatu, tv∙rci STL se takticky omezili na maximßln∞ binßrnφ funkce, ale to nenφ na zßvadu, i tak STL pokr²vß Üirokou Ükßlu b∞₧n²ch pot°eb. Pokud n∞kdo pot°ebuje t°eba ternßrnφ funkce (n = 3), m∙₧e si je podle jednoduchΘho receptu doprogramovat.
  18. Minule jsme takΘ poznali, ₧e by bylo dobrΘ, kdyby se funktor choval jako (Φφselnß) hodnota. V podstat∞ jde o to, aby jej bylo mo₧nΘ bezpeΦn∞ kopφrovat (kopφrovacφ konstruktor) nebo p°i°adit (operßtor =). STL jde dßl a p°φmo to na°izuje - vÜechny koncepty funkcφ zjem≥ujφ koncept Assignable, kter² po₧aduje prßv∞ uvedenΘ vlastnosti (value semantics). ObyΦejnΘ funkce se chovajφ jako hodnoty, nebo¥ p°ekladaΦ s nimi pracuje pomocφ ukazatel∙ Φi referencφ. U funktor∙ je dodr₧enφ po₧adovan²ch vlastnostφ odpov∞dnostφ programßtora.
  19. Minule jsme takΘ narazili na potφ₧, ₧e se n∞kterΘ (zejmΘna obyΦejnΘ) funkce nedaly adaptovat. Proto STL rozliÜuje generßtory a adaptabilnφ generßtory, unßrnφ funkce a adaptabilnφ unßrnφ funkce atd. O tom, co v STL tento p°φvlastek znamenß, se doΦtete dßle.
  20.  
  21. Adaptabilnφ modely
  22. D∙vod, proΦ se nßm neda°ilo obyΦejnΘ funkce adaptovat, byl prost²: p°ekladaΦ nenaÜel vno°enΘ definice typ∙. A o totΘ₧ jde v STL - adaptabilnφ funkce (funktor) musφ mφt vno°enΘ definice typ∙ argument∙ a typu v²sledku. STL nßm ulehΦuje prßci tφm, ₧e poskytuje dv∞ ÜablonovΘ t°φdy, jednu pro unßrnφ a druhou pro binßrnφ funkce, kterΘ obsahujφ (pouze) pot°ebnΘ vno°enΘ definice typ∙. Pokud nßÜ funktor odvodφme (d∞d∞nφ v duchu OOP) od takovΘ t°φdy, bude mφt automaticky po₧adovanΘ definice typ∙, a bude tedy adaptabilnφ. Tyto dv∞ pomocnΘ t°φdy vypadajφ takto:
  23. // p°edek pro unßrnφ
  24. // adaptabilnφ funktory
  25. template <class ARGUMENT, 
  26.           class VYSLEDEK>
  27. struct unary_function
  28. {
  29.    typedef ARGUMENT argument_type;
  30.    typedef VYSLEDEK result_type;
  31. };
  32.  
  33. // p°edek pro binßrnφ
  34. // adaptabilnφ funktory
  35. template <class ARG1, class ARG2,
  36.           class VYSLEDEK>
  37. struct binary_function
  38. {
  39.    typedef ARG1 first_argument_type;
  40.    typedef ARG1 second_argument_type;
  41.    typedef VYSLEDEK result_type;
  42. };
  43. STL nedefinuje ₧ßdnou podobnou t°φdu pro generßtory (funktory volanΘ bez parametr∙). Ale to nevadφ, programßtor m∙₧e snadno vytvo°it adaptabilnφ generßtor i bez toho. A jeÜt∞ jedna d∙le₧itß poznßmka. Abychom vytvo°ili adaptabilnφ funktor, nemusφme jej nutn∞ odvodit od v²Üe uveden²ch t°φd, pot°ebnΘ definice typ∙ m∙₧eme samoz°ejm∞ vepsat ruΦn∞ - p°esn∞ tak jako v minulΘm dφlu.
  44.  
  45. Operßtory
  46. ╚asto pot°ebujeme pou₧φt n∞kter² z aritmetick²ch, logick²ch nebo relaΦnφch operßtor∙. A proto₧e vestav∞nΘ operßtory nelze p°edat funkci pomocφ ukazatele ani reference, musφme na to jφt oklikou a "zabalit" je do funktor∙; jejich seznam naleznete v tabulce 1. Teoreticky by se daly zabalit i do obyΦejn²ch vlo₧en²ch funkcφ, ale tφm bychom se p°ipravili o mo₧nost vno°en²ch definic typ∙ a ztratili tak adaptabilitu.
  47. Jak vypadß implementace, si ukß₧eme na jednoduchΘm p°ikladu unßrnφho minus:
  48. template <class T>
  49. struct negate
  50.    : public unary_function<T, T>
  51. {
  52.    // operßtor volßnφ funkce
  53.    T operator()(const T & arg) const
  54.    {
  55.       return -arg;
  56.    }
  57. };
  58. Ostatnφ t°φdy jsou vytvo°eny podle stejnΘho receptu. Vno°enΘ definice typ∙ se zd∞dφ po p°edcφch, vÜechny tyto funktory jsou tedy adaptabilnφ. P°φklady pou₧itφ naleznete na Chip CD 2/01. Zde si jen krßtce ukß₧eme, jak po slo₧kßch seΦφst dva kontejnery c1 a c2 (obsahujφcφ celß Φφsla typu int) a v²sledek ulo₧it do c1:
  59. transform(c1.begin(), c1.end(),
  60.    c2.begin(), c1.begin(), plus<int>());
  61.  
  62. KlasickΘ funkce
  63. Aby byla klasickß funkce modelem adaptabilnφ funkce, musφme k nφ p°idat vno°enΘ definice typ∙ a vÜechno to zabalit do specißlnφho adaptΘru. JakΘ prost°edky pro tento ·Φel poskytuje STL, vidφme v tabulce 2.
  64. Vytvo°ujφcφ funkce se jmenuje stejn∞ pro unßrnφ i binßrnφ funkce - o rozliÜenφ se postarß p°ekladaΦ (docela p∞knß ukßzka p°et∞₧ovßnφ funkcφ). RozsßhlejÜφ p°φklady naleznete op∞t na Chip CD, zde alespo≥ kratiΦkou etudu, jak v kontejneru c Φφsel typu double nahradit ka₧d² prvek jeho druhou odmocninou:
  65. transform(c.begin(), c.end(),
  66.    c.begin(), ptr_fun(sqrt));
  67.  
  68. ╚lenskΘ funkce objektov²ch typ∙
  69. Pokud by nßm nestaΦily ani operßtory, ani obyΦejnΘ funkce, m∙₧eme jeÜt∞ pou₧φt metody objektov²ch typ∙. Zde mφsto obyΦejnΘho ukazatele na funkci pracujeme s ukazatelem do t°φdy. Situace je vÜak slo₧it∞jÜφ, nebo¥ do hry vstupujφ reference a metody konstantnφch objekt∙. P°ehled standardem definovan²ch adaptΘr∙ a jejich vlastnostφ uvßdφ tabulka 3. Zjistφme v nφ mimo jinΘ, ₧e potomci unßrnφ funkce (unary_function) jsou ve skuteΦnosti ΦlenskΘ funkce bez parametr∙ - jedin²m parametrem je toti₧ instance, pro kterou se tato Φlenskß funkce volß. Stejn∞ tak potomci binßrnφ funkce jsou unßrnφ ΦlenskΘ funkce.
  70. Na prvnφ pohled to vypadß slo₧it∞, ale snad pom∙₧e krßtk² p°φklad. Definujeme t°φdu numero, kterß zapouzd°φ typ double (viz soubor f15_stl_mem_fun.cpp na Chip CD):
  71. class numero
  72. {
  73. public:
  74.    // ... n∞jakΘ metody ...
  75.    // vrati odmocnene numero
  76.    numero get_sqrt() const;
  77.    // odmocni "toto" numero 
  78.    void do_sqrt();
  79. private : 
  80.    double x_;
  81. }; 
  82. Do n∞jakΘho kontejneru s ulo₧φme blφ₧e nespecifikovan² poΦet instancφ tΘto t°φdy. Budeme chtφt spoΦφtat odmocniny vÜech prvk∙ a ulo₧it je do kontejneru t (p°edpoklßdejme, ₧e t mß stejn∞ prvk∙ jako s). Musφme pou₧φt Φlenskou metodu get_sqrt: 
  83. transform(s.begin(), s.end(), t.begin(),
  84.       mem_fun_ref(&numero::get_sqrt));
  85. Pokud bychom do kontejneru, nap°. seznamu, uklßdali jen ukazatele na t°φdu numero, tj.
  86. list<numero *> u;
  87. a cht∞li bychom vÜechna tato "numera" (na mφst∞) odmocnit, staΦilo by napsat
  88. for_each(u.begin(), u.end(), 
  89.    mem_fun(&numero::do_sqrt));
  90. a vÜe by bylo v po°ßdku.
  91.  
  92. Standardnφ adaptΘry
  93. Kdy₧ je t°eba fixovat parametr...
  94. Jak zafixovat jeden z parametr∙ binßrnφ funkce, u₧ vφme z minula. Nynφ se podφvßme, jak se to d∞lß v STL. AdaptΘr, kter² fixuje parametr, se anglicky naz²vß binder (bind znamenß fixovat, vßzat). Implementace t∞chto adaptΘr∙ v STL je ovÜem pon∞kud slo₧it∞jÜφ ne₧ ta naÜe - je toti₧ koncipovßna obecn∞, pro jakoukoli adaptabilnφ binßrnφ funkci (funktor). Zde nßm postaΦφ jejich p°ehled v tabulce 4.
  95. Pro ukßzku navß₧eme na p°φklady z minulΘho dφlu: mßme op∞t kontejner cisla cel²ch Φφsel typu int a chceme najφt prvnφ kladn² a prvnφ zßporn² prvek. Pou₧ijeme k tomu standardnφ binßrnφ funktor greater z tab. 1.
  96. // prvnφ kladn² (>0)
  97. find_if(cisla.begin(), cisla.end(),
  98.    bind2nd(greater<int>(), 0));
  99.  
  100. // prvnφ zßporn² (<0)
  101. find_if(cisla.begin(), cisla.end(),
  102.    bind1st(greater<int>(), 0));
  103.  
  104. ... nebo negovat v²sledek
  105. Negovat v²sledek u₧ takΘ umφme z minula. P°φsluÜn² adaptΘr se naz²vß negßtor. V STL jsou k dispozici dva: jeden pro unßrnφ a druh² pro binßrnφ funkce (predikßty), viz tabulka 5.
  106. Tφm jsme probrali vÜechny standardnφ funktory i adaptΘry a nastal Φas na n∞jak² komplexn∞jÜφ p°φklad. ╪ekn∞me, ₧e kontejner v obsahuje °et∞zce (typ string) a funkce porovnej je analogiφ standardnφ funkce strcmp pro °et∞zce typu string. Tipn∞te si, co ud∞lß nßsledujφcφ p°φkaz:
  107. replace_if(v.begin(), v.end(), 
  108.    not1(bind2nd(ptr_fun(porovnej), "C")),
  109.    "C++");
  110. Odpov∞∩ najdete na Chip CD 2/02 (hrajte fΘr a zkuste nejd°φve potrßpit vlastnφ hlavu...).
  111.  
  112. Jak napsat vlastnφ funktor
  113. P°i prßci s STL se obΦas dostaneme do situace, kdy pot°ebujeme generickΘmu algoritmu vnutit n∞jakou Φinnost, kterou mß provΘst s prvky kontejneru a kterou nelze realizovat prost°edky STL. Nezb²vß ne₧ napsat bu∩ klasickou funkci, nebo jeÜt∞ lΘpe - vytvo°it funktor.
  114. P°edem si musφme ujasnit n∞kolik otßzek:
  115. * P∙jde o unßrnφ, nebo binßrnφ funkci?
  116. * JakΘ jsou typy argument∙ a v²sledku?
  117. * StaΦφ nßm klasickß funkce, nebo to musφ b²t funktor?
  118. * Pot°ebujeme adaptabilnφ, nebo postaΦφ neadaptabilnφ funktor?
  119. * Odvodit (nebo neodvodit) nßÜ funktor jako potomka t°φdy unary_function, nebo binary_function?
  120. ╪eÜenφ prvnφch dvou otßzek je zßsadnφ, odpov∞di na ostatnφ otßzky pouze urΦujφ kvalitu implementace. Nesmφme takΘ zapomenout, ₧e instance funktor∙ se p°edßvajφ hodnotou.
  121. Uva₧ujme jednoduch² p°φklad. Mßme kontejner cisla hodnot typu double a chceme n∞jak zpracovat jejich odchylky od jistΘ hodnoty (t°eba jejich aritmetickΘho pr∙m∞ru). Ud∞lßme to tak, ₧e odchylky budeme uklßdat jednu po druhΘ do jinΘho, p°edem vyprßzdn∞nΘho kontejneru, kter² pojmenujeme t°eba odchylky. NapφÜeme si funktor, kter² bude poΦφtat odchylky (nebo p°φmo rovnou jejich mocniny). V naÜem p°φpad∞ p∙jde o unßrnφ funktor (zkuste si rozmyslet proΦ). NejjednoduÜÜφ je neadaptabilnφ funktor, t°eba takov²:
  122. class cOdchylkaNeadapt
  123. {
  124. public:
  125.    cOdchylkaNeadapt(double odceho, 
  126.                     int mocnina) 
  127.       : od_ceho_(odceho),
  128.         mocnina_(mocnina)
  129.       {}
  130.    double operator ()(double x);
  131. private:
  132.    double od_ceho_;
  133.    int mocnina_;
  134. };
  135. Funktor v tΘto podob∞ by nßm te∩ staΦil, ale zkusme jej zm∞nit na adaptabilnφ. (Je to takovß investice do budoucna - nikdy nevφme, kdy se to bude hodit.) StaΦφ bu∩ doplnit vno°enΘ definice typ∙, stejn∞ jako v minulΘm dφlu, nebo jeÜt∞ lΘpe - odvodit nßÜ funktor od STL t°φdy unary_function:
  136. class cOdchylkaAdaptSTL : public 
  137.    unary_function<double, double>
  138. {
  139. public:
  140.    cOdchylkaAdaptSTL(double odceho, 
  141.                      int mocnina) 
  142.       : od_ceho_(odceho), 
  143.         mocnina_(mocnina) 
  144.       {}
  145.    double operator ()(double x);
  146. private:
  147.    double od_ceho_;
  148.    int mocnina_;
  149. };
  150. Vno°enΘ definice typ∙ se zd∞dφ od p°edka. P°φklady pou₧itφ obou funktor∙ se prakticky neliÜφ, tak₧e jeden za oba: 
  151. transform(cisla.begin(), cisla.end(),
  152.    odchylky.begin(), cOdchylkaNeadapt(0.0, 2));
  153. Jist∞ jste poznali, ₧e zde poΦφtßme kvadratickΘ odchylky od nuly za pomoci neadaptabilnφho funktoru.
  154.  
  155. Jak napsat vlastnφ adaptΘr
  156. Podobn∞ postupujeme p°i vytvß°enφ adaptΘru funktoru - bude to toti₧ takΘ funktor. P°i zjiÜ¥ovßnφ typ∙ argument∙ a v²sledku se m∙₧eme "zeptat" adaptovanΘho funktoru. Tvorb∞ r∙zn²ch ukßzkov²ch adaptΘr∙ jsme se v∞novali u₧ minule, nynφ si ukß₧eme adaptΘr, kter² implementuje sklßdßnφ dvou funkcφ. Mßme stßle kontejner cisla hodnot typu double a chceme vÜechna Φφsla nejprve nahradit jejich absolutnφ hodnotou a pak odmocnit.
  157. // pomocnß definice typu
  158. typedef double (* FUNC)(double); 
  159.  
  160. class cSkladani
  161. {
  162. public:
  163.    cSkladani(FUNC prvni, FUNC druha)
  164.       : prvni_(prvni), druha_(druha) 
  165.       {}
  166.    double operator ()(double x) 
  167.       { 
  168.          return druha_(prvni_(x)); 
  169.       }
  170. private:
  171.    FUNC prvni_;
  172.    FUNC druha_;
  173. };
  174. Vytvo°ili jsme neadaptabilnφ adaptΘr, kter² se postarß o slo₧enΘ volßnφ dvou unßrnφch funkcφ typu FUNC. Pou₧itφ by pak mohlo vypadat t°eba takto:
  175. transform(cisla.begin(), cisla.end(),
  176.    cisla.begin(), cSkladani(fabs, sqrt));
  177.  
  178. ┌skalφ, podrazy a pr∙Üvihy 
  179. ObΦas pot°ebujeme zjistit, kolikrßt byl dan² funktor volßn. Takov² pokus ale v STL obvykle skonΦφ krachem. Dejme tomu, ₧e jsme do funktoru p°idali ΦφtaΦ, kter² se p°i ka₧dΘm zavolßnφ zv²Üφ o jedniΦku:
  180. class cFunktor
  181. {
  182. public:
  183.    int operator ()(int x)
  184.    {
  185.       ++pocet_;
  186.       // n∞jakΘ akce ...
  187.    }
  188.    int get_pocet() { return pocet_; }
  189.    void reset_pocet() { pocet_ = 0; }
  190. private:
  191.    int pocet_;
  192.    // ...
  193. };
  194. A pak jej pou₧ijeme n∞jak takto:
  195. // POZOR, TAKHLE TO NEFUNGUJE
  196. cFunktor funktor;
  197. funktor.reset_pocet();
  198. transform(cisla.begin(), cisla.end(),
  199.           cisla.begin(), funktor);
  200. cout << "pocet volani = " 
  201.      << funktor.get_pocet() << endl;
  202. A¥ je Φφsel, kolik chce, v₧dy se vypφÜe nula. U vÜech generick²ch algoritm∙ v STL se toti₧ funkce Φi funktor p°edßvajφ hodnotou. To znamenß, ₧e se vytvo°φ kopie, kterß bude ·sp∞Ün∞ poΦφtat, kolikrßt byla volßna, ale my se to nedozvφme, nebo¥ tato kopie zanikne p°i nßvratu z funkce transform. Jednou z mo₧nostφ nßpravy by bylo pou₧φt v definici funktoru ukazatel Φi referenci na ΦφtaΦ le₧φcφ n∞kde vn∞ funktoru (ale to s sebou nese zase jinß rizika...).
  203. DalÜφ "zßdrhel", na kter² je t°eba pamatovat: P°i pou₧itφ funkce transform standard negarantuje, ₧e se prvky budou prochßzet od zaΦßtku a po jednom. Jedinou jistotou je, ₧e funktor (nebo funkce) se zavolß pro ka₧d² prvek v danΘm rozsahu prßv∞ jednou. Co to znamenß? M∞jme unßrnφ predikßt, kter² vracφ true pro t°etφ prvek a false pro vÜechny ostatnφ:
  204. class cTreti
  205. {
  206. public:
  207.    cTreti() : pocet_(0) {}
  208.    bool operator ()(int)
  209.    {
  210.       return ++pocet_ == 3;
  211.    }
  212. private:
  213.    int pocet_;
  214. };
  215. Cht∞jme te∩ t°etφ prvek kontejneru cislo nahradit ekvivalentem true (z°ejm∞ 1), ostatnφ ekvivalentem false (0).
  216. // POZOR, NEMUS═ FUNGOVAT
  217. transform(cisla.begin(), cisla.end(),
  218.           cisla.begin(), cTreti());
  219. Bude to fungovat, jak chceme? Odpov∞∩ znφ: Mo₧nß, jak kde. Jde toti₧ o nep°enositeln² k≤d, kter² se v r∙zn²ch p°ekladaΦφch m∙₧e chovat r∙zn∞, a standard to dovoluje! (Pravda vÜak je, ₧e ve vÜech mn∞ znßm²ch implementacφch se chovß stejn∞ - prochßzφ prvky od zaΦßtku do konce a po jednom, ale standard je standard...)
  220. Jinou zßle₧itost, na ni₧ je t°eba upozornit, bych bez vßhßnφ oznaΦil za "p∞kn² podraz". V nßsledujφcφm progrßmku chceme odstranit t°etφ prvek z kontejneru cisla (funkce remove_if vracφ iterßtor na konec rozsahu po odebrßnφ prvk∙; pokud tam zbude n∞jak² "cancour", zlikvidujeme jej pomocφ metody erase):
  221. // POZOR, NEMUS═ FUNGOVAT!
  222. cisla.erase(remove_if(cisla.begin(),
  223.                 cisla.end(),
  224.                 cTreti()), 
  225.       cisla.end());
  226. Je-li p∙vodnφ posloupnost 
  227. 1 2 3 4 5 6 7 8 9,
  228. mß tedy v²slednß posloupnost b²t
  229. 1 2 4 5 6 7 8 9.
  230. K naÜemu velkΘmu p°ekvapenφ se vÜak m∙₧eme doΦkat v²sledku
  231. 1 2 4 5 7 8 9.
  232. Jak je to mo₧nΘ? Odpov∞∩ nalezneme v definici ÜablonovΘ funkce remove_if. Ta m∙₧e vypadat t°eba takto:
  233. template <class ITER, class PREDIKAT>
  234. ITER remove_if(ITER beg, ITER end, 
  235.                PREDIKAT op)
  236. {
  237.   beg = find_if(beg, end, op);  // !!
  238.   if (beg == end) { return beg; }
  239.   else {
  240.     ITER next = beg;
  241.     return remove_copy_if(++next, 
  242.                  end, beg, op); // !!
  243.   }
  244. }
  245. Na °ßdcφch oznaΦen²ch dv∞ma vyk°iΦnφky se volajφ dalÜφ funkce z STL a nßÜ funktor je jim p°edßn hodnotou. To znamenß, ₧e se vytvß°ejφ kopie, kterΘ pak p°ed nßvratem do funkce remove_if op∞t zaniknou. A mßme problΘm: nßÜ predikßt mß sv∙j vnit°nφ stav (nastavenφ slo₧ky pocet_), pomocnΘ funkce ale tento stav zm∞nφ u kopie, kterß zanikne, tak₧e se o zm∞n∞ nedozvφme. Co je vÜak jeÜt∞ horÜφ - standard p°edepisuje pro funkci remove_if pouze rozhranφ, nikoli implementaci. Tak₧e u n∞kter²ch implementacφ to m∙₧e fungovat, jak Φekßme, u jin²ch ne.
  246. Vezm∞me si z toho alespo≥ toto pouΦenφ: Pozor na predikßty (ale i obecnΘ funktory) s vnit°nφm stavem, kter² zßvisφ na jednotliv²ch volßnφch predikßtu (funktoru). ObΦas nahlΘdnout do zdrojov²ch k≤d∙ implementace STL se urΦit∞ vyplatφ...
  247.  
  248. Optimistick² zßv∞r
  249. AΦkoli p°edchozφ °ßdky nevyzn∞ly zvlßÜt∞ pozitivn∞, pova₧uji funktory za mocn² nßstroj a takΘ jej s ·sp∞chem vyu₧φvßm ve sv²ch programech. JistΘ je, ₧e pokud programujete pomocφ STL a jejφch generick²ch algoritm∙, bez funktor∙ se prost∞ neobejdete. Budi₧ vßm tento Φlßnek oporou...
  250.  
  251. Jaroslav Fran∞k
  252.  
  253. infotipy
  254. [1] Mezinßrodnφ standard jazyka C++, ICO/IEC 14882:1998
  255. [2] J. Fran∞k: Jak se na funktor volß... (1), Chip 1/02
  256. [3] J. Fran∞k: Nebojte se STL, Chip 12/01
  257. [4] S. Meyers: Effective STL, ISBN 0-201-74962-9
  258. [5] dokumentace knihovny STL od SGI: www.sgi.com/tech/stl
  259. [6] zdrojov² k≤d v rubrice Chip Plus na Chip CD 2/02
  260.  
  261.