home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 February / Chip_2001-02_cd1.bin / obsahy / Chip_txt / TXT / 142-145.TXT < prev    next >
Text File  |  2000-12-27  |  17KB  |  375 lines

  1. èablonovΘ metaprogramovßnφ v C++
  2. D°inu nechte p°ekladaΦi!
  3. èablonovΘ metaprogramovßnφ (template metaprogramming) je velice zajφmavß technika, vhodnß p°edevÜφm pro tvorbu knihoven a optimalizaci k≤du. Jejφ poΦßtky se datujφ p°ibli₧n∞ do roku 1994 a od tΘ doby se postupn∞ vyvinula v pou₧iteln² a nad∞jn² prost°edek, kter², alespo≥ pokroΦil²m, urΦit∞ stojφ za seznßmenφ...
  4.  
  5. Rozvφjejφcφ se standard C++ umo₧nil n∞co, o Φem se d°φve nikomu ani nesnilo: p°idat do jazyka C++ kvalitativn∞ novou vrstvu û metaprogramovßnφ. Prost°edkem jsou Üablony (templates), kterΘ zmi≥ovan² standard znaΦn²m zp∙sobem rozÜφ°il. Pomocφ Üablon lze emulovat zßkladnφ konstrukce programovacφch jazyk∙, jako v∞tvenφ (if-then-else, switch) nebo smyΦky (for, do-while, while). Ukß₧eme si, jak na to.
  6.  
  7. Metatypy
  8. Prom∞nn²mi v ÜablonovΘm metaprogramovßnφ jsou typy a celß Φφsla (p°esn∞ji °eΦeno vÜechno, co m∙₧e b²t argumentem Üablony). Vzhledem k tomu, ₧e metaprogram je provßd∞n b∞hem kompilace, musφ b²t Φφsla z pohledu klasickΘho C++ konstanty. I v ÜablonovΘm metaprogramovßnφ lze rozliÜit prom∞nnΘ, konstanty a literßly. ZaΦneme s jednoduch²mi p°φklady:
  9. const int N = 1;
  10. template <int M> class A {};
  11.  
  12. void funkce()
  13. {
  14.  A<N> a; // zde p°i°adφme M = N
  15. }
  16. Zde N je metakonstanta, M je metaprom∞nnß, 1 je celoΦφseln² metaliterßl (p°edpony meta majφ naznaΦit vztah k metaprogramu). Samoz°ejm∞, N je zßrove≥ konstanta a 1 je celoΦφseln² literßl. A nynφ pro zm∞nu typy:
  17. typedef int X;
  18. template <class T> class B {};
  19.  
  20. void funkce()
  21. {
  22.  B<X> b; // zde p°i°adφme T = X
  23. }
  24. Jde o analogii p°edchozφho p°φkladu: X je (typovß) metakonstanta, T je (typovß) metaprom∞nnß, int je (typov²) metaliterßl. I bez slo₧it²ch definic by m∞lo b²t jasnΘ, co je co.
  25.  
  26. Metaoperace
  27. Uka₧me si te∩, jak pomocφ Üablon zapsat n∞kterΘ jednoduchΘ metaoperace. ZaΦneme u nßsobenφ:
  28. template <int M, int N> struct MetaMUL
  29. {
  30.  static cont int RETURN = M*N;
  31. };
  32. Pou₧φt to m∙₧eme t°eba takto:
  33. template <int M, int N> class Matice // matice M x N
  34. {
  35.  // ... uvedeno jen to podstatnΘ
  36.  static const int PocetPrvku()
  37.  {
  38.   return MetaMUL<M, N>::RETURN;
  39.  }
  40. };
  41. Metoda PocetPrvku() vrßtφ poΦet prvk∙ matice, tj. M*N. M∙₧ete namφtnout, ₧e to je zbyteΦn∞ slo₧itΘ a mφsto metaoperace MetaMUL by zde Ülo pou₧φt klasickou operaci nßsobenφ. JednoduchΘ smysluplnΘ p°φklady metaprogramovßnφ se vÜak t∞₧ko hledajφ a musφme se zatφm spokojit s t∞mi mΘn∞ smyslupln²mi.
  42. Ostatnφ operace s cel²mi Φφsly lze definovat analogicky. Uvedeme jeÜt∞ jeden p°φklad û porovnßnφ:
  43. template <int M, int N> struct MetaEQ
  44. {
  45.  static const bool RETURN = (M == N);
  46. };
  47. Porovnßnφ je operace, kterou m∙₧eme implementovat i pro typy. V tomto p°φpad∞ musφme ale pou₧φt ΦßsteΦnou specializaci Üablon:
  48. template <class T1, class T2> struct MetaEQTYPE
  49. {
  50.  static const bool RETURN = false;
  51. }
  52.  
  53. template <class T> struct MetaEQTYPE<T, T>
  54. {
  55.  static const bool RETURN = true;
  56. }
  57. Smyslupln² p°φklad pou₧itφ se sem bohu₧el nevejde, tak alespo≥ to nejjednoduÜÜφ, co lze napsat:
  58. MetaEQTYPE<int, double>::RETURN; // v²raz 1
  59. MetaEQTYPE<int, int>::RETURN; // v²raz 2
  60. Pokud p°ekladaΦ narazφ na v²raz 1, pou₧ije nespecializovanou Üablonu, a tudφ₧ hodnotu false. Pro v²raz 2 se pou₧ije specializovanß Üablona a hodnota true.
  61.  
  62. Metafunkce
  63. Od metaoperacφ je jen kr∙Φek k metafunkcφm. Uka₧me si vyu₧itφ rekurze v hodnotovΘm parametru Üablony na klasickΘm p°φkladu v²poΦtu faktorißlu. Faktorißl nezßpornΘho celΘho Φφsla n je definovßn rekurzivn∞ takto:
  64. 0! = 1
  65. n! = n.(n-1)!
  66. A nynφ v Üablonßch:
  67. template <int N> struct MetaFactorial
  68. {
  69.  static const int F = N*MetaFactorial<N-1>::F;
  70. };
  71.  
  72. // explicitnφ specializace, ukonΦenφ rekurze
  73. template <> struct MetaFactorial<0>
  74. {
  75.  static const int F = 1;
  76. };
  77. Co na to p°ekladaΦ? Pokud narazφ na v²raz MetaFactorial<N>::F, pokusφ se vyΦφslit jeho hodnotu takto:
  78. if (N == 0)
  79. {
  80.  pou₧ij specializovanou t°φdu MetaFactorial<0>
  81.   MetaFactorial<0>::F = 1
  82. }
  83. else  // N > 0
  84. {
  85.  pou₧ij nespecializovanou t°φdu MetaFactorial<N>
  86.    je t°eba urΦit MetaFactorial<N-1>::F,
  87.    a proto pou₧ij rekurzivn∞ tento postup pro N-1
  88.  prove∩ nßsobenφ N*cFaktorial<N-1>::F
  89. }
  90. Pokud v programu napφÜeme cFaktorial<4>::F, p°ekladaΦ to nahradφ v dob∞ p°ekladu konstantou 24 û v²poΦet faktorißlu tedy nenφ zßle₧itostφ b∞hu programu, ale p°ekladaΦe! V²poΦet faktorißlu byl op∞t tφm nejjednoduÜÜφm p°φkladem. M∙₧eme ovÜem vyΦφslovat i mnohem komplikovan∞jÜφ funkce, dokonce i odmocniny:
  91. template <int SIZE, int LOW = 1, int HIGH = SIZE>
  92. struct MetaRoot;
  93. {
  94.  static const int mean = (LOW+HIGH)/2;
  95.  static const bool down = (mean*mean >= SIZE);
  96.  static const int root =
  97.   MetaRoot<SIZE, (down ? LOW : mean+1),
  98.            (down ? mean : HIGH)>::root;
  99. };
  100.  
  101. // ΦßsteΦnß specializace 
  102. template <int SIZE, int MID>
  103. struct MetaRoot<SIZE, MID, MID>
  104. {
  105.  static const int root = MID;
  106. };
  107. V²raz sRoot<N>::root je ekvivalentem v²razu std::ceil(std::sqrt(N)), tj. je to hornφ celß Φßst odmocniny z N; lze jej pou₧φt na mφst∞, kde je oΦekßvßna konstanta, nap°. p°i deklaraci statickΘho pole:
  108. const int N = 10;
  109. int tabulka[sRoot<N>::root];
  110. JeÜt∞ poznßmka: Tento p°φklad, aΦkoliv je zcela v souladu se standardem jazyka C++, v mΘm p°ekladaΦi (C++ Builder 4.0) nefunguje. ProblΘm je v deklaraci prvnφ Üablony. P°ekladaΦ si nedokß₧e poradit s implicitnφm argumentem u ÜablonovΘho parametru HIGH (tj. int HIGH = SIZE). Ohlßsφ vnit°nφ chybu a skonΦφ. Doufejme, ₧e v nov∞jÜφch p°ekladaΦφch u₧ to bude lepÜφ.
  111.  
  112. Meta-if
  113. V∞tvenφ pat°φ mezi zßkladnφ programovΘ konstrukce a v metaprogramovßnφ mß takΘ svΘ mφsto. Vytvo°φme primßrnφ Üablonu t°φdy
  114. template <bool B> struct MetaIF {};
  115. a explicitnφ specializaci pro argumenty true a false:
  116. template <> struct MetaIF<true>
  117. {
  118.  static void Neco();
  119. };
  120.  
  121. template <> struct MetaIF<false> {};
  122. Toto je implementace ne·plnΘho meta-if (kde chybφ sekce else). P°φklad pou₧itφ:
  123. MetaIF<(sizeof(int) > 2)>::Neco();
  124. ZapiÜme schematicky, co chceme od p°ekladaΦe
  125. if (sizeof(int) > 2)
  126. {
  127.  pou₧ij t°φdu MetaIF<true>
  128.  zavolej metodu MetaIF<true>::Neco()
  129. }
  130. else
  131. {
  132.  pou₧ij t°φdu MetaIF<false>
  133.  metoda MetaIF<false>::Neco() nenφ definovanß
  134.   ohlaÜ chybu
  135. }
  136. Pokud bychom cht∞li emulovat ·plnΘ meta-if, staΦφ dodefinovat metodu MetaIF<false>::Neco(). Poznamenejme jeÜt∞, ₧e pro pou₧itφ MetaIF<B> je nutnΘ, aby B byl v²raz vyΦφsliteln² v dob∞ p°ekladu a p°evoditeln² na typ bool. 
  137.  
  138. Meta-switch
  139. Na podobnΘm principu funguje i emulace konstrukce switch. Vytvo°φme primßrnφ Üablonu t°φdy MetaCASE. Ta pak bude slou₧it jako sekce default v p°φkazu switch.
  140. template <int I> struct MetaCASE
  141. {
  142.  static int NecoDelej() {return 0;}
  143. };
  144. Nynφ pro ka₧dou hodnotu, kterß by se vyskytla v nßv∞Ütφ case, vytvo°φme explicitnφ specializaci.
  145. template <> struct MetaCASE<1>
  146. {
  147.  static int NecoDelej() {return 1;}
  148. };
  149.  
  150. template <> struct MetaCASE<2>
  151. {
  152.  static int NecoDelej() {return 2;}
  153. };
  154. ┌loha p°ekladaΦe:
  155. p°i v²skytu MetaCASE<I> hledej vhodnou specializaci takto:
  156. switch (I)
  157. {
  158.  case 1 :
  159.  {
  160.   pou₧ij specializovanou t°φdu MetaCASE<1>
  161.   zavolej metodu MetaCASE<1>::NecoDelej()
  162.   break
  163.  }
  164.  case 2 :
  165.  {
  166.   pou₧ij specializovanou t°φdu MetaCASE<2>
  167.   zavolej metodu MetaCASE<2>::NecoDelej()
  168.   break
  169.  }
  170.  default :
  171.  {
  172.   pou₧ij nespecializovanou t°φdu MetaCASE<I>
  173.   zavolej metodu MetaCASE<I>::NecoDelej()
  174.   break
  175.  }
  176. }
  177. P°φklad pou₧itφ:
  178. std::cout << MetaCASE<1>::NecoDelej() << " "
  179.           << MetaCASE<3>::NecoDelej();
  180. Na obrazovce se objevφ v²pis "1 0" (samoz°ejm∞ ani toto nenφ zrovna smyslupln² p°φklad...). 
  181. Zkusme si jeÜt∞ ukßzat, jak m∙₧eme Üablonami nahradit n∞kterß makra pro podmφn∞n² p°eklad. 
  182. Makra:
  183. #if defined(__PROSTREDI_16_BITU) // int je 2B
  184. // k≤d pro 16bitovΘ prost°edφ
  185. #elif defined(__PROSTREDI_32_BITU) // int je 4B
  186. // k≤d pro 32bitovΘ prost°edφ
  187. #else
  188.  #error Neni definovano prostredi
  189. #endif
  190. TotΘ₧ pomocφ Üablon:
  191. template <int VELIKOSTINT> struct MetaProstredi {};
  192.  
  193. template <> struct MetaProstredi<2>
  194. {
  195.  static void KodZavislyNaVelikostiInt()
  196.  {
  197.  // k≤d pro 16bitovΘ prost°edφ
  198.  }
  199. };
  200.  
  201. template <> struct MetaProstredi<4>
  202. {
  203.  static void KodZavislyNaVelikostiInt()
  204.  {
  205.  // k≤d pro 32bitovΘ prost°edφ
  206.  }
  207. };
  208.  
  209. // nahradφ makra v p°edchozφm p°φkladu:
  210. MetaProstredi<sizeof(int)>::KodZavislyNaVelikostiInt();
  211.  
  212. MetasmyΦky
  213. Emulace smyΦek je zalo₧ena na rekurzi v hodnotovΘm parametru Üablony. PoΦet pr∙chod∙ smyΦkou musφ b²t znßm v dob∞ p°ekladu. Klasicky by to mohlo vypadat takto:
  214. void funkce(int i)
  215. {
  216.  std::cout << i; // n∞jakß akce
  217. }
  218.  
  219. const int N = 10;
  220. for (int i = 0 ; i <= N ; i++) funkce(i);
  221. A nynφ pomocφ Üablon:
  222. template <int I> struct MetaLOOP
  223. {
  224.  static void loop()
  225.  {
  226.   MetaLOOP<I-1>::loop(); // rekurze
  227.   std::cout << I;     // n∞jakß akce
  228.  }
  229. };
  230.  
  231. // explicitnφ specializace, ukonΦφ rekurzi
  232. template <> struct MetaLOOP<0>
  233. {
  234.  static void loop()
  235.  {
  236.   std::cout << 0; // n∞jakß akce
  237.  }
  238. };
  239. Uka₧me si, co se stane, kdy₧ p°ekladaΦ narazφ na konstrukci MetaLOOP<N>::loop(), kde N je konstanta znßmß v dob∞ p°ekladu:
  240. if (N == 0)
  241. {
  242.  pou₧ij specializovanou t°φdu MetaLOOP<0>
  243.  zavolej metodu MetaLOOP<0>::loop()
  244.   (naÜe metoda vypφÜe na obrazovku hodnotu 0)
  245. }
  246. else  // N > 0
  247. {
  248.  pou₧ij nespecializovanou t°φdu MetaLOOP<N>
  249.  zavolej metodu MetaLOOP<N>::loop()
  250.  v  metod∞ MetaLOOP<N>::loop()
  251.   je t°eba zavolat metodu MetaLOOP<N-1>::loop(),
  252.   proto pou₧ij rekurzivn∞ tento postup pro N-1
  253.  potom prove∩ dalÜφ instrukce v metod∞
  254.   MetaLOOP<N>::loop()
  255.   (naÜe metoda vypφÜe na obrazovku hodnotu N)
  256. }
  257. To v praxi znamenß, ₧e p°φkaz MetaLOOP<2>::loop() vypφÜe na obrazovku °et∞zec "012". Nejd°φve se zavolß MetaLOOP<2>::loop(), ta zavolß MetaLOOP<1>::loop() a ta zavolß MetaLOOP<0>::loop(). Zde dojde k v²pisu hodnoty 0. Vracφme se do funkce MetaLOOP<1>::loop(), kde dojde k v²pisu hodnoty 1. Nakonec se vrßtφme do MetaLOOP<2>::loop(), kde se vypφÜe hodnota 2. Pokud bychom cht∞li obrßtit sled hodnot, staΦφ zam∞nit po°adφ rekurze a "akce" v metod∞ MetaLOOP<I>::loop():
  258. template <int I> struct MetaLOOP
  259. {
  260.  static void loop()
  261.  {
  262.   std::cout << i;  // n∞jakß akce
  263.   MetaLOOP<I-1>::funkce();    // rekurze
  264.  }
  265. };
  266. Nynφ by p°φkaz MetaLOOP<2>::loop() vypsal na obrazovku °et∞zec "210". A nynφ se dostßvßme k nevφdan²m mo₧nostem optimalizace: Pokud budou metody deklarovßny jako vlo₧enΘ, tj. deklarovßny s pou₧itφm klφΦovΘho slova inline nebo definovßny uvnit° t°φdy (jako zde), nebude p°ekladaΦ volat funkce, ale p°φmo tam vlo₧φ k≤d. Navφc je to ud∞lßno rekurzivn∞, tak₧e p°ekladaΦ v p°φpad∞ p°φkazu MetaLOOP<2>::loop() vygeneruje nßsledujφcφ k≤d (pro p∙vodnφ vzestupnou verzi):
  267. std::cout << 0;
  268. std::cout << 1;
  269. std::cout << 2;
  270. Ani zmφnka o n∞jakΘ smyΦce Φi volßnφ funkce! V angliΦtin∞ se to oznaΦuje jako loop transformation, tedy transformace smyΦky do jednosm∞rnΘ posloupnosti p°φkaz∙. Tφmto zp∙sobem je mo₧nΘ donutit p°ekladaΦ optimalizovat na rychlost: odstranφ se smyΦka (testovßnφ v²razu, skok na zaΦßtek nebo na konec smyΦky) i volßnφ funkcφ (ulo₧enφ a odstran∞nφ parametr∙ v zßsobnφku, skok do funkce a nßvrat z funkce).
  271. Podmφnkou ovÜem je, aby poΦet opakovßnφ smyΦky byl znßm v dob∞ p°ekladu a byl mal² (viz zßv∞reΦnΘ poznßmky). Proto tento p°φstup nelze pou₧φt v₧dy. Velice vhodn² je pro tzv. "malΘ" vektory a matice. O co jde? M∞jme za ·kol naprogramovat knihovnu pro prßci s vektory (samoz°ejm∞ pomocφ Üablon). Vytvo°φme Üablonu t°φdy cVektorA tak, jak nßs to uΦφ uΦebnice C++:
  272. template <class TYP> class cVektorA
  273. {
  274. public:
  275.  cVektorA(int velikost)
  276.   : Velikost(velikost), Data(new TYP [velikost]) {}
  277.  ~cVektorA() {delete [] Data;}
  278.  // ... uvedeny jsou jen d∙le₧itΘ v∞ci
  279.  TYP operator *(cVektorA<TYP> & v);  // skalßrnφ souΦin
  280. private:
  281.  TYP * Data;
  282.  int Velikost;
  283. };
  284.  
  285. // p°etφ₧en² operßtor *, skalßrnφ souΦin
  286. template <class TYP>
  287. TYP cVektorA<TYP>::operator *(cVektorA<TYP> & v)
  288. {
  289.  // problΘm 1: nelze provΘst pro odliÜnΘ velikosti
  290.  if (Velikost != v.Velikost)
  291.  {
  292.   throw std::logic_error("* nelze provΘst pro vektory"
  293.                                  "odliÜnΘ velikosti");
  294.  }
  295.  // problΘm 2: neefektivnφ pro "male Velikosti"
  296.  TYP suma = 0;
  297.  for (int i = 0 ; i < Velikost ; i++)
  298.  {
  299.   suma += Data[i] * v.Data[i];
  300.  }
  301.  return suma;
  302. }
  303. V definici p°etφ₧enΘho operßtoru nßsobenφ jsou naznaΦeny n∞kterΘ problΘmy. NaÜφm cφlem je co nejrychlejÜφ k≤d, tak₧e pro malΘ vektory to zkusφme jinak û s pou₧itφm ÜablonovΘho metaprogramovßnφ. Novß t°φda cVektor bude parametrizovßna takΘ velikostφ vektoru.
  304. template <class TYP, int VELIKOST> class cVektor
  305. {
  306. public:
  307.  cVektor() : Data(new TYP [VELIKOST]) {}
  308.  ~cVektor() {delete [] Data;}
  309.  // ... uvedeny jsou jen d∙le₧itΘ v∞ci
  310.  TYP operator *(cVektor<TYP, VELIKOST> & v);
  311. private:
  312.  TYP * Data;
  313. };
  314.  
  315.  // pomocnΘ t°φdy pro implementaci skalßrnφho souΦinu
  316. template <class TYP, int VELIKOST> struct MetaDOT
  317. {
  318.  static inline TYP apply(const TYP * a, const TYP * b)
  319.  {
  320.   return (*a) * (*b) +
  321.    MetaDOT<TYP, VELIKOST-1>::apply(a+1, b+1);
  322.  }
  323. };
  324.  
  325. // ΦßsteΦn∞ specializovanß t°φda (ukonΦenφ rekurze)
  326. template <class TYP> struct MetaDOT<TYP, 1>
  327. {
  328.  static inline TYP apply(const TYP * a, const TYP * b)
  329.  {
  330.   return (*a) * (*b);
  331.  }
  332. };
  333.  
  334. // a nynφ implementace operßtoru skalßrnφho souΦinu
  335. template <class TYP, int VELIKOST> inline TYP
  336. cVektor<TYP, VELIKOST>::operator *(cVektor<TYP, VELIKOST> & v)
  337. {
  338.  // nenφ problΘm 1, velikosti jsou stejnΘ
  339.  // velice efektivnφ pro male VELIKOSTi -> nenφ problΘm 2
  340.  return MetaDOT<TYP, VELIKOST>::apply(Data, v.Data);
  341. }
  342. Jak vidφte, je skalßrnφ souΦin dvou vektor∙ p°ekladaΦem p°etransformovßn do tvaru
  343. Data[0]*v.Data[0] + Data[1]*v.Data[1] + ... +
  344. Data[VELIKOST-1]*v.Data[VELIKOST-1]
  345. co₧ je tΘm∞° optimßlnφ tvar. Stejn∞ tak m∙₧eme optimalizovat sΦφtßnφ, odΦφtßnφ, inicializaci, kopφrovßnφ atd. Na Chip CD (viz infotipy) naleznete mj. zdrojov² soubor metaloop_02.cpp, ve kterΘm je dopln∞n jednoduch² test rychlosti. Pro VELIKOST==2 je metak≤d asi Φty°icetkrßt (!) rychlejÜφ ne₧ p∙vodnφ implementace pomocφ smyΦek. Pro rostoucφ VELIKOST tento pom∞r klesß.
  346.  
  347. N∞kolik poznßmek na konec
  348. Metak≤d je mo₧no zapsat r∙zn²mi zp∙soby. V p°edchozφm jsme vÜechny operace implementovali pomocφ Üablon t°φd (struct, class) a jejich statick²ch atribut∙ a metod. N∞kte°φ auto°i obΦas pou₧φvajφ i Üablony funkcφ nebo mφsto statick²ch atribut∙ pou₧φvajφ v²ΦtovΘ typy (enum).
  349. Pou₧itφ funkcφ nenφ zrovna nejchyt°ejÜφ. Statickß metoda t°φdy poskytuje v podstat∞ totΘ₧ co funkce. Navφc do t°φdy je mo₧no vlo₧it mnoho dalÜφch d∙le₧it²ch informacφ, nap°. o typu vracenΘ hodnoty, kterΘ je mo₧nΘ v metak≤du vyu₧φt.
  350. V²ΦtovΘ typy p°edstavujφ alternativu statick²ch atribut∙. Ale pozor: P°i pou₧itφ v²Φtov²ch typ∙ i statick²ch atribut∙ jsem narazil na zßva₧nΘ problΘmy v n∞kter²ch p°ekladaΦφch (Borland C++ Builder 4.0); rozhodn∞ se v₧dy vyplatφ pßr pokus∙ p°edem.
  351. DalÜφ omezenφ se mohou vyskytnout v souvislosti se smyΦkami. Nejde toti₧ o nic jinΘho ne₧ o rekurzivnφ vytvß°enφ instancφ Üablon. Norma doporuΦuje tv∙rc∙m p°ekladaΦ∙ podporovat  hloubku rekurze minimßln∞ 17. R∙znΘ p°ekladaΦe se ovÜem mohou liÜit. Borland C++ Builder 4.0 dovolφ v n∞kter²ch p°φpadech dosßhnout hloubky rekurze v∞tÜφ ne₧ 1000 (!), jindy zase nejvφce 86 û prost∞ poka₧dΘ je to jinak (viz infotipy û ukßzky program∙ na Chip CD). Proto znovu p°ipomφnßm, ₧e je t°eba experimentovat.
  352.  
  353. Zßv∞r
  354. Hlavnφ v²znam ÜablonovΘho metaprogramovßnφ spoΦφvß v optimalizaci v²slednΘho k≤du z hlediska rychlosti. Z p°ekladaΦe se tak vlastn∞ stßvß interpret, kter² podle naÜich instrukcφ (metaprogramu) nejd°φve vygeneruje tΘm∞° optimßlnφ k≤d a ten pak p°elo₧φ. Metaprogram nenφ nic jinΘho ne₧ chyt°e vytvo°enΘ deklarace Üablon t°φd a jejich specializacφ. Rychlost v²slednΘho k≤du je pak srovnatelnß s rychlostφ po ruΦnφ optimalizaci.
  355. SouΦasnΘ p°ekladaΦe ovÜem zatφm majφ s n∞kter²mi konstrukcemi problΘmy. Nenφ se co divit û v∞tÜina z nich jeÜt∞ pln∞ neimplementuje Üablony tak, jak to vy₧aduje standard, a nßpis na krabici "Full ANSI/ISO template implementation" Φasto vyjad°uje spφÜe p°ßnφ ne₧ skuteΦnost.
  356. Knihovny napsanΘ pomocφ ÜablonovΘho metaprogramovßnφ lze nalΘzt na internetu. Mezi nejlepÜφ pat°φ Blitz++ a Matrix Template Library, kterΘ p°edstavujφ implementaci lineßrnφ algebry a n∞kter²ch numerick²ch algoritm∙. Tam takΘ hledejte dalÜφ, praktiΦt∞jÜφ p°φklady konstrukcφ, kterΘ jsme si zde p°edstavili.
  357. Optimalizace pomocφ Üablon samoz°ejm∞ nekonΦφ u mal²ch vektor∙. Optimalizovat lze takΘ operace provßd∞nΘ s velk²mi vektory, o tom vÜak snad n∞kdy p°φÜt∞.
  358.  
  359. Jaroslav Fran∞k
  360.  
  361. infotipy
  362. Standard C++:
  363. International standard ISO/IEC 14882, Programming languages û C++. 1998-09-01.
  364. Blitz++:
  365. http://oonumerics.org/blitz/
  366. MTL:
  367. http://www.lsc.nd.edu/research/mtl/
  368. P°edchozφ Φlßnek:
  369. èablony po Üesti letech, Chip 12/00, str. 192.
  370. Ukßzky program∙:
  371. Chip CD 1/01, rubrika Chip Plus, Metaprogramy.
  372.     Chyba! Neznßm² argument p°epφnaΦe./1
  373.  
  374.  
  375.