home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 November / Chip_2001-11_cd1.bin / obsahy / Chip_txt / txt / 196-199.txt < prev    next >
Text File  |  2001-09-30  |  17KB  |  237 lines

  1. Jazyk C++
  2. èablona t°φdy a deklarace friend
  3. V tomto p°φsp∞vku si povÜimneme zßle₧itostφ, kterΘ proÜly tak bou°liv²m v²vojem, ₧e p°i tvorb∞ standardu byly n∞kolikrßt m∞n∞ny a nakonec doÜlo i na zm∞nu jejich sΘmantiky, tak₧e chyb p°i programovßnφ je dost a dost. Snad se te∩ alespo≥ n∞kter²m vyhnete...
  4.  
  5. Kde se vzala slo₧itost C++
  6. N∞kde na poΦßtku byl jazyk C. Jazyk to byl dobr², pou₧φvß se dodnes. Byl ale poznamenßn dobou svΘho vzniku, kdy objektov∞ orientovanΘ programovßnφ teprve Φekalo na svΘ objevenφ. Prßv∞ o n∞ se "cΘΦko" rozhodl rozÜφ°it Bjarne Stroustrup - vznikl jazyk C++. Ale ani to zanedlouho nestaΦilo a doÜla °ada i na generickΘ programovßnφ. A tak C++ rostlo, rostlo, a₧ sv²m tv∙rc∙m trochu p°erostlo p°es hlavu (o programßtorech, kte°φ tento jazyk pou₧φvajφ, ani nemluv∞). Dokladem m∙₧e b²t jeho mezinßrodnφ standard ISO/IEC 14882:1998 - vφce ne₧ 700 stran pln²ch slo₧it²ch a n∞kdy tΘm∞° nepochopiteln²ch pravidel mluvφ samo za sebe. Nenφ se co divit, ₧e i tv∙rci p°ekladaΦ∙ majφ co d∞lat, aby sprßvn∞ pochopili a implementovali po₧adovanΘ vlastnosti.
  7. ProΦ takovß slo₧itost? Odpov∞∩ nenφ tak t∞₧kß. Pokud majφ vedle sebe existovat r∙znß (ale opravdu r∙znß) programovacφ paradigmata, je t°eba oÜet°it jejich "styΦnΘ plochy". Vezm∞me t°eba objektov∞ orientovanΘ programovßnφ a generickΘ programovßnφ. Prvnφ p°edstavuje znovupou₧itelnost na ·rovni binßrnφch komponent, kde₧to druhΘ znovupou₧itelnost na ·rovni zdrojovΘho k≤du, tedy n∞co zcela odliÜnΘho. Jsou-li pak ob∞ souΦßstmi jednoho programovacφho jazyka, je kv∙li konzistenci nutnΘ zavΘst spoustu pravidel regulujφcφch vzßjemn² vztah obou paradigmat. A k tomu C++ jeÜt∞ navφc podporuje procedurßlnφ (strukturovanΘ) programovßnφ, ÜablonovΘ metaprogramovßnφ a kdovφ co jeÜt∞ - asi u₧ je jasnΘ, kde se vzalo t∞ch 700 stran a proΦ je to tak slo₧itΘ.
  8. V tΘto souvislosti je vhodnΘ zmφnit jazyky Java a C#. Zde Üli auto°i jinou cestou. Prost∞ zvolili programovacφ paradigma, kterΘ je zrovna (komerΦn∞) nej·sp∞Ün∞jÜφ, a ta ostatnφ bu∩ vypustili ·pln∞ (jako se to stalo Üablonßm), nebo omezili do pat°iΦn²ch mezφ (t°eba unsafe k≤d v C#). Proto jsou tyto jazyky "pr∙hledn∞jÜφ" ne₧ C++. (Je to samoz°ejm∞ pohled trochu zjednoduÜen²; vφc se dozvφte nap°. v [4].)
  9. Ale poj∩me zp∞t k C++ a proberme si jednu z jeho "lah∙dek" - st°et hned t°φ paradigmat: generickΘho programovßnφ (Üablona t°φdy, funkce), objektov∞ orientovanΘho programovßnφ (deklarace friend) a procedurßlnφho programovßnφ (obyΦejnß funkce). Tato Φßst byla v pr∙b∞hu standardizace n∞kolikrßt zm∞n∞na, p°iΦem₧ neÜlo jen o p°idßnφ novΘ syntaxe, ale i o zm∞nu v²znamu n∞kter²ch d°φve pou₧φvan²ch konstrukcφ. SluÜφ se proto upozornit ty, kdo pou₧φvajφ voln∞ dostupnou pracovnφ verzi standardu z roku 1996, ₧e tato Φßst je ve finßlnφ verzi zm∞n∞na.
  10.  
  11. N∞co je zase jinak...
  12. V²klad zaΦneme trochu netradiΦn∞ Φastou chybou, kterß je d∙sledkem zm∞ny sΘmantiky deklarace friend. Tuto chybu nejdete i v autorov∞ "typickΘ" implementaci vektoru v Φlßnku o Üablonßch v²raz∙ [3]. P°itom jeÜt∞ p°ed n∞kolika lety by bylo vÜe v po°ßdku. Za toto "nedopat°enφ, ke kterΘmu dochßzφ nejv²Üe jednou za 10 let..." se autor Φtenß°∙m omlouvß.
  13. Nejd°φve si p°ipome≥me onu zmi≥ovanou typickou implementaci vektoru:
  14. template <class T>
  15. class Vektor
  16. {
  17. public:
  18.   // ...
  19. friend
  20.   Vektor<T> operator +(
  21.     const Vektor<T> & v1,
  22.     const Vektor<T> & v2);
  23. private:
  24.   T * data_;
  25.   int size_;  // velikost
  26. };
  27.  
  28. // Üablona globßlnφho operßtoru +
  29. template <class T>
  30. Vektor<T> operator +(
  31.     const Vektor<T> & v1,
  32.     const Vektor<T> & v2)
  33. {
  34.   Vektor<T> pom(v1.size_);
  35.   for (int i = 0; i < pom.size_; ++i) 
  36.   {
  37.     pom.data_[i] = 
  38.         v1.data_[i] + v2.data_[i];
  39.   }
  40.   return pom;
  41. }
  42. Konstruktor, destruktor a ostatnφ metody jist∞ dokß₧ete doplnit sami. Nezapome≥te na kopφrovacφ konstruktor, ten zde hraje d∙le₧itou roli - provßdφ tzv. hlubokou kopii (deep copy), kterß je nutnß pro sprßvnou funkci nap°. operßtoru sΦφtßnφ (p°φkaz return pom;).
  43. Tento k≤d je syntakticky v po°ßdku - to znamenß, ₧e jej lze bez potφ₧φ p°elo₧it. ProblΘm nastane, kdy₧ n∞kde dßl budeme chtφt sp°ßtelen² operßtor sΦφtßnφ pou₧φt:
  44. Vektor<double> a;
  45. Vektor<double> b;
  46. // ...
  47. a + b;    // !
  48. Ve starÜφch p°ekladaΦφch (nap°. Borland C++ 5.0) to projde bez povÜimnutφ a vÜe funguje. NovΘ p°ekladaΦe, kterΘ se °φdφ standardem ISO jazyka C++ (nap°. Borland C++ Builder 4.0 nebo 5.0), k≤d sice p°elo₧φ, ale nedokß₧φ ho slinkovat. Objevφ se chybovΘ hlßÜenφ o tom, ₧e linkovacφ program nem∙₧e nalΘzt operßtor
  49. Vektor<double> operator+(
  50.     const Vektor<double> &, 
  51.     const Vektor<double> &);
  52. Na prvnφ pohled to vypadß jako chyba p°ekladaΦe. Co je tedy jinak? Abychom na to dokßzali odpov∞d∞t, musφme nejd°φve podniknout v²zkumnou v²pravu do on∞ch 700 stran standardu C++. Zajφmat nßs bude v²znam deklarace friend, a to v souvislosti se Üablonami.
  53.  
  54. Cesta do hlubin standardu C++
  55. Zde jsou zßkladnφ pravidla (standard [1], sekce 14.5.3.1):
  56. P°φtelem t°φdy nebo ÜablonovΘ t°φdy m∙₧e b²t Üablona t°φdy Φi funkce, specializace Üablony t°φdy Φi funkce nebo obyΦejnß (neÜablonovß) funkce Φi t°φda. Pro deklaraci sp°ßtelenΘ funkce, kterß nenφ Üablonovou deklaracφ, platφ:
  57. [1] jestli₧e jmΘno sp°ßtelenΘ funkce je kvalifikovanΘ nebo nekvalifikovanΘ id-Üablony, pak deklarace odpovφdß danΘ specializaci ÜablonovΘ funkce, jinak
  58. [2] jestli₧e jmΘno sp°ßtelenΘ funkce je kvalifikovanΘ a p°φsluÜnß neÜablonovß funkce je nalezena ve specifikovanΘ t°φd∞ nebo prostoru jmen, pak deklarace odpovφdß tΘto funkci, jinak
  59. [3] jestli₧e jmΘno sp°ßtelenΘ funkce je kvalifikovanΘ a ve specifikovanΘ t°φd∞ nebo prostoru jmen je nalezena odpovφdajφcφ specializace ÜablonovΘ funkce, pak deklarace odpovφdß tΘto specializaci, jinak
  60. [4] musφ jφt o nekvalifikovanΘ jmΘno, kterΘ deklaruje (nebo re-deklaruje) obyΦejnou (neÜablonovou) funkci.
  61. Abychom se v takovΘhle hr∙ze mohli vyznat, nejd°φve si trochu objasn∞me terminologii. 
  62. * Vysv∞tlenφ pojmu specializace Üablony naleznete v Φlßnku [2].
  63. * JmΘna mohou b²t kvalifikovanß nebo nekvalifikovanß. Operßtor kvalifikace je :: ("Φty°teΦka"). ZjednoduÜen∞ °eΦeno, pokud je souΦßstφ jmΘna operßtor ::, jde o kvalifikovanΘ jmΘno. P°φklady:
  64. neco       // nekvalifikovanΘ jmΘno
  65. ::neco     // vÜechna ostatnφ jsou kvalifikovanß
  66. MojeTrida::neco
  67. ProstorJmen::neco
  68. ProstorJmen::MojeTrida::neco
  69. * id-Üablony je jmΘno Üablony nßsledovanΘ seznamem Üablonov²ch argument∙ v lomen²ch zßvorkßch. Pokud majφ n∞kterΘ ÜablonovΘ parametry deklarovßny implicitnφ argumenty, je mo₧nΘ je vynechat (podle analogick²ch pravidel jako u implicitnφch argument∙ funkcφ); nesmφme vÜak vynechat lomenΘ zßvorky - i kdy₧ jsou prßzdnΘ. P°φklady:
  70. neco<T>  // nekvalifikovanΘ id-Üablony
  71. ::MojeTrida<double, 3>
  72. ProstorJmen::neco<>
  73.  
  74. A te∩ prakticky...
  75. Nynφ si projd∞te uvedenß pravidla jeÜt∞ jednou a pokuste se vy°eÜit nßsledujφcφ ·kol. Mßme n∞kolik deklaracφ funkcφ oznaΦen²ch (1) a₧ (5) a Üablonovou t°φdu Trida, ve kterΘ jsou deklarace sp°ßtelen²ch t°φd a funkcφ. Pokuste se vysv∞tlit, co jednotlivΘ deklarace znamenajφ, a v p°φpad∞ deklaracφ sp°ßtelen²ch funkcφ urΦit, kterß z deklaracφ (1) a₧ (4) je jimi myÜlena, p°φpadn∞ podle kterΘho z pravidel [1] a₧ [4] bylo rozhodnuto.
  76. template <class T> class Trida;
  77.  
  78. class MojeTrida;
  79. template <class U> class MojeSablTrida;
  80.  
  81. template <class T> void f(Trida<T> &);  // (1)
  82. void f(Trida<int> &);  // (2)
  83. template <class T> void g(Trida<T> &);  // (3)
  84. template <class T> void h(T); // (4)
  85. void h();  // (5)
  86.  
  87. template <class T> class Trida
  88. {
  89.    // sp°ßtelenΘ t°φdy
  90.    friend class MojeTrida;   // (a)
  91.    template <class U> 
  92.       friend class MojeSablTrida;  // (b)
  93.    friend class Trida<int>;  // (c)
  94.  
  95.    // sp°ßtelene funkce f
  96.    friend void f<T>(Trida<T> &);  // (d)
  97.    // friend void ::f<T>(Trida<T> &);  // (e)
  98.    friend void ::f(Trida<T> &);  // (f)
  99.    friend void f(Trida<T> &);  // (g)
  100.    
  101.    // sp°ßtelene funkce g
  102.    friend void g<T>(Trida<T> &);  // (h)
  103.    // friend void ::g<T>(Trida<T> &);  // (i)
  104.    friend void ::g(Trida<T> &);  // (j)
  105.    friend void g(Trida<T> &);  // (k)
  106.  
  107.    // ten zbytek
  108.    friend void h();   // (l)
  109.    template <class U> friend void h(U); // (m)
  110. };
  111. ╪eÜenφ:
  112. (a) Deklarujeme sp°ßtelenou t°φdu MojeTrida pro vÜechny specializace ÜablonovΘ t°φdy Trida.
  113. (b) Deklarujeme sp°ßtelenou Üablonovou t°φdu MojeSablTrida. VÜechny specializace ÜablonovΘ t°φdy MojeSablTrida budou sp°ßtelenΘ s jakoukoliv specializacφ ÜablonovΘ t°φdy Trida.
  114. (c) Ka₧dß specializace ÜablonovΘ t°φdy Trida bude mφt sp°ßtelenou t°φdu Trida<int>.
  115. (d) Deklarace sp°ßtelenΘ funkce; pou₧ijeme tedy v²Üe uvedenß pravidla. Jednß se o nekvalifikovanΘ id-Üablony, pou₧ije se proto pravidlo [1] a deklarace (1). Znamenß to tedy jistΘ provßzßnφ Üablonov²ch argument∙: funkce f<T> je sp°ßtelenß s t°φdou Trida<T>.
  116. (e) Stejn∞ jako (c) s jedin²m rozdφlem - jde o kvalifikovanΘ id-Üablony.
  117. (f) Zde je situace slo₧it∞jÜφ. Musφme rozliÜit dva p°φpady. Jestli₧e T je int, pak podle pravidla [2] je pou₧ita neÜablonovß funkce (2). Pokud T nenφ int, pak podle pravidla [3] jde o funkci (1). (Vzhledem ke zkuÜenostem s b∞₧n²mi p°ekladaΦi berte toto zatφm jako sci-fi.)
  118. (g) NekvalifikovanΘ jmΘno; podle pravidla [4] je to neÜablonovß funkce f. Jde o obyΦejnou (neÜablonovou) funkci, jejφ₧ parametry p°φmo zßvisφ na Üablonov²ch parametrech t°φdy Trida. To znamenß, ₧e deklarace (2) pokr²vß pouze jednu mo₧nost, kdy T je int. Kdyby T byl jak²koliv jin² typ, museli bychom dodefinovat p°φsluÜnou neÜablonovou funkci.
  119. (h) Analogicky jako v bodu (c); pravidlo [1] urΦφ deklaraci (3).
  120. (i) Analogicky jako v bodu (d); pravidlo [1] urΦφ deklaraci (3).
  121. (j) KvalifikovanΘ jmΘno; nenφ nalezena ₧ßdnß vhodnß neÜablonovß funkce, tak₧e podle pravidla [3] se jednß o deklaraci (3), tj. pou₧ije se specializace ÜablonovΘ funkce.
  122. (k) NekvalifikovanΘ jmΘno; podle pravidla [4] je to neÜablonovß funkce g (dokonce jejφ deklarace). Takovß funkce tu vÜak nenφ definovßna. P°esto nemusφ jφt o chybu - stejn∞ jako v p°φpad∞ (g) deklarace friend °φkß, ₧e pokud takovß funkce existuje, pak je sp°ßtelenß - nic vφc. Stejn∞ jako v p°φpad∞ (f) je zde zßvislost parametr∙ funkce na Üablonov²ch parametrech t°φdy Trida.
  123. (l) Sp°ßtelenou funkcφ je obyΦejnß °adovß funkce; pravidlo [4], deklarace (5). Jeliko₧ parametry tΘto funkce v∙bec nesouvisφ se Üablonov²mi parametry t°φdy Trida, je tato funkce sp°ßtelenß s jakoukoliv specializacφ t°φdy Trida.
  124. (m) Deklarujeme sp°ßtelenou Üablonovou funkci h; deklarace (4). Zde se pravidla [1] a₧ [4] nepou₧φvajφ, nebo¥ jde o Üablonovou deklaraci. VÜechny specializace ÜablonovΘ funkce h jsou sp°ßtelenΘ s jakoukoliv specializacφ ÜablonovΘ t°φdy Trida.
  125.  
  126. Co je jeÜt∞ dobrΘ v∞d∞t
  127. Deklarace sp°ßtelenΘ funkce, kterß nenφ zßrove≥ Üablonovou deklaracφ a ve kterΘ je jmΘno funkce nekvalifikovanΘ id-Üablony, musφ odkazovat na Üablonu funkce v nejbli₧Üφm nad°φzenΘm prostoru jmen.
  128. template <class T> void f(T);
  129. void g(int);  // alias ::g
  130.  
  131. namespace N 
  132. {
  133.    template <class T> void h(T);
  134.  
  135.    class A
  136.    {
  137.       // ...
  138.       friend void f<>(int);  // nelze
  139.       friend void h<>(int);  // OK, N::h
  140.       friend void g(int); // OK, 
  141.       // deklarace funkce N::g, nikoli ::g
  142.    };
  143. }
  144. VÜimn∞te si takΘ, ₧e deklarace sp°ßtelenΘ funkce g (ve skuteΦnosti N::g) nemß s globßlnφ funkcφ g nic spoleΦnΘho.
  145. Jako p°φtele m∙₧eme deklarovat Üablonu funkce - p°φpad (m), nebo t°φdy - p°φpad (b). Je zde jeden rozdφl: p°φsluÜnou funkci smφme definovat uvnit° t°φdy (tedy na mφst∞ deklarace friend), kde₧to sp°ßtelenou t°φdu ne.
  146. class A
  147. {
  148.    template <class T> friend void f(T) { /*...*/ }  // OK
  149.    template <class T> friend class B;  // pouze deklarace
  150. };
  151. èablona funkce Φi t°φdy nem∙₧e b²t p°φtelem lokßlnφ t°φdy, tj. t°φdy definovanΘ uvnit° n∞jakΘ funkce.
  152. Pokud deklarace sp°ßtelenΘ funkce odkazuje na specializaci ÜablonovΘ funkce, nesmφ se v deklaraci parametr∙ vyskytnout implicitnφ argumenty ani nesmφ b²t pou₧ito klφΦovΘ slovo inline.
  153.  
  154. Jak to tedy bylo
  155. Nynφ se vrßtφme k naÜemu problΘmu z ·vodu Φlßnku. Ve sv∞tle nov²ch poznatk∙ m∙₧eme °φci, ₧e deklarace friend deklaruje °adovou funkci, nikoli specializaci Üablony; viz pravidlo [4]. To znamenß, ₧e p°ekladaΦ nepou₧ije nßmi nabφzenou Üablonu operßtoru + k vytvo°enφ specializace a oΦekßvß, ₧e si pot°ebnou operßtorovou funkci napφÜeme sami. To jsme vÜak neud∞lali, a proto ji linkovacφ program nenaÜel. Museli bychom dodefinovat °adovou neÜablonovou funkci
  156. Vektor<double> operator+(
  157.     const Vektor<double> &, 
  158.     const Vektor<double> &);
  159. Ale co kdy₧ pou₧ijeme Vektor<int>? Nastane zase ta samß chyba. Museli bychom jeÜt∞ napsat operßtorovou funkci
  160. Vektor<int> operator+(
  161.     const Vektor<int> &, 
  162.     const Vektor<int> &);
  163. A tak dßle pro vÜechny mo₧nΘ typy... Je jist∞ jasnΘ, ₧e takhle jsme to necht∞li. Musφme proto provΘst n∞kolik ·prav. Pro snazÜφ orientaci budou tyto ·pravy v dalÜφm textu zv²razn∞ny.
  164. ╪eÜenφ 1
  165. Provedeme propojenφ Üablonov²ch argument∙ pou₧itφm id-Üablony v deklaraci friend.
  166.  
  167. // p°edb∞₧nΘ deklarace
  168. template <class T> class Vektor;
  169.  
  170. template <class T>
  171. Vektor<T> operator +(
  172.     const Vektor<T> & v1,
  173.     const Vektor<T> & v2);
  174.  
  175. // upravenß t°φda Vektor
  176. template <class T>
  177. class Vektor
  178. {
  179. public:
  180.   // ...
  181. friend 
  182.   Vektor<T> operator +<T>(
  183.     const Vektor<T> & v1,
  184.     const Vektor<T> & v2);
  185. private:
  186.   T * data_;
  187.   int size_;  // velikost
  188. };
  189. èablona operßtoru + z∙stane beze zm∞ny. Rozdφl je tedy v tom, ₧e p°i deklaraci sp°ßtelenΘ funkce uvedeme explicitn∞ ÜablonovΘ argumenty, tj. mφsto operator+ napφÜeme operator+<T>. Tφm se provß₧e specializace t°φdy Vektor se specializacφ operßtoru +. P°itom je nutnΘ poskytnout p°ekladaΦi p°edem informace o tom, ₧e mßme Üablonu operßtoru +. To jsou ony p°edb∞₧nΘ deklarace. Nynφ vÜe funguje tak, jak jsme cht∞li.
  190. ╪eÜenφ 2
  191. P°edchozφ °eÜenφ p°edpoklßdß, ₧e p°φsluÜn² operßtor + bude pouze specializace Üablony. Pokud bychom pro n∞jak² typ m∞li k dispozici odpovφdajφcφ neÜablonovou operßtorovou funkci, mßme sm∙lu. Ale ne tak docela - m∙₧eme na to jφt trochu jinak:
  192. // p°edb∞₧nΘ deklarace
  193. template <class T> class Vektor;
  194.  
  195. // Üablona operßtoru +
  196. template <class T>
  197. Vektor<T> operator +(
  198.     const Vektor<T> & v1,
  199.     const Vektor<T> & v2);
  200.  
  201. // neÜablonov² operßtor +
  202. Vektor<int> operator +(
  203.    const Vektor<int> & v1,
  204.    const Vektor<int> & v2); 
  205.  
  206. // upravenß t°φda Vektor
  207. template <class T>
  208. class Vektor
  209. {
  210. public:
  211.   // ...
  212. friend 
  213.   Vektor<T> ::operator +(
  214.     const Vektor<T> & v1,
  215.     const Vektor<T> & v2);
  216. private:
  217.   T * data_;
  218.   int size_;  // velikost
  219. };
  220. Finta spoΦφvß v pou₧itφ kvalifikovanΘho jmΘna (a nepou₧itφ id-Üablony). Nynφ do hry vstupujφ pravidla [2] a [3]. Pro t°φdu Vektor<int> je podle pravidla [2] nalezena neÜablonovß operßtorovß funkce. Pro vÜechny ostatnφ specializace t°φdy Vektor se pou₧ije Üablona operßtoru + podle pravidla [3].
  221. JeÜt∞ poznamenejme, ₧e pot°eba pou₧itφ neÜablonovΘ funkce namφsto Üablony b²vß Φasto spojena s optimalizacφ. èablona je sama o sob∞ dost obecnß zßle₧itost a pro n∞kterΘ specifickΘ typy m∙₧e b²t lepÜφ naprogramovat dan² ·kol jinak. Je sice mo₧nΘ pou₧φt explicitnφ specializaci, ale n∞kdy snad m∙₧e b²t dobrΘ pou₧φt neÜablonovou funkci. Jazyk C++ nenutφ pou₧φvat to Φi ono, ale pokud jedno z toho pou₧ijeme, mßme jistotu, ₧e si s tφm dokß₧e poradit (alespo≥ teoreticky).
  222.  
  223. Zßv∞r
  224. Pokud nepou₧ijeme Üablony, je p°ßtelstvφ v C++ pom∞rn∞ snadnou zßle₧itostφ. Jakmile do hry vstoupφ Üablony, je t°eba dßvat velk² pozor na to, co jednotlivΘ deklarace p°ßtel znamenajφ. Jeliko₧ doÜlo ke zm∞n∞ v²znamu n∞kter²ch konstrukcφ, mohou se objevit problΘmy p°i kompilaci (a linkovßnφ) starÜφch program∙. 
  225. Typick²m p°φkladem je v²Üe zmφn∞nß implementace t°φdy a sp°ßtelenΘho operßtoru. Vzhledem ke stavu dneÜnφch p°ekladaΦ∙ je lΘpe pou₧φt "╪eÜenφ 1", tj. provßzat ÜablonovΘ argumenty.
  226. A nakonec jeÜt∞ malß poznßmka k tΘ p∙vodnφ "typickΘ" implementaci. I kdy₧ tam p°ipφÜeme neÜablonovou definici pot°ebnΘho operßtoru, majφ s tφm p°ekladaΦe Borland C++ Builder problΘmy. Verze 4 ohlßsφ chybu ji₧ p°i generovßnφ (!) k≤du a pokroΦilejÜφ verze 5 obΦas skonΦφ se zßhadnou  chybou p°i linkovßnφ. Naproti tomu Microsoft Visual C++ 6.0 s tφm problΘmy nemß.
  227. Ukßzky k≤du naleznete na Chip CD 10/01 v rubrice Chip Plus. N∞kterΘ v∞ci vÜak bohu₧el jeÜt∞ nefungujφ tak, jak by podle standardu m∞ly...
  228.  
  229. Jaroslav Fran∞k
  230.  
  231. Literatura
  232. [1] Standard C++: International standard ISO/IEC 14882, 1998-09-01
  233. [2] M. Virius: èablony po Üesti letech, Chip 12/00
  234. [3] J. Fran∞k: èablony v²raz∙, Chip 4/01
  235. [4] M. Virius: Kafe, m°φ₧ a dva plusy, Chip 7/01 a 8/01
  236.  
  237.