Diferente pentru blog/metaprogramare-cu-template-uri intre reviziile #7 si #8

Nu exista diferente intre titluri.

Diferente intre continut:

*Principiul de baza*
Poate stiti ca in STL exista o implementare generala pentru vector, insa exista si o implementare speciala numai pentru vector<bool>, care foloseste doar cate un bit pentru fiecare valoare. Idioma C++ care permite asa ceva este "template specialization" si este un mecanism foarte puternic (mult mai puternic decat vom vedea aici). Practic, compilatorul are mai multe definitii din care alege una anume. Folosind acest lucru putem sa "trucam" compilatorul in a face un "if".
Poate stiti ca in STL exista o implementare generala pentru vector, insa exista si o implementare speciala numai pentru _vector<bool>,_ care foloseste doar cate un bit pentru fiecare valoare. Idioma C++ care permite asa ceva este "template specialization" si este un mecanism foarte puternic (mult mai puternic decat vom vedea aici). Practic, compilatorul are mai multe definitii din care alege una anume. Folosind acest lucru putem sa "trucam" compilatorul in a face un "if".
De exemplu, sa zicem ca vrem sa facem o asertie la timpul compilarii. Avem o expresie statica (care poate fi calculata la compilare) si vrem sa primim o eroare daca aceasta expresie nu se evalueaza la true. Putem sa folosim aceasta idee de template specialization:
CompileTimeError<expr>::Cool
==
Daca expr = true, s-ar evalua la 1. Insa daca este false, vom avea o eroare de compilare - definitia generala nu include identificatorul Cool. Am reusit sa facem compilatorul sa evalueze doua lucruri diferite in functie de o expresie - un "if" daca vreti.
Daca _expr = true_, s-ar evalua la 1. Insa daca este _false_, vom avea o eroare de compilare - definitia generala nu include identificatorul _Cool_. Am reusit sa facem compilatorul sa evalueze doua lucruri diferite in functie de o expresie - un "if" daca vreti.
*Recursivitate*
Pentru ca tipurile sunt prin definitie imutabile, nu vom putea face compilatorul sa ruleze algoritmi iterativi - nu avem cum sa il facem sa mentina o stare. Va trebui sa convertim orice lucru iterativ in ceva recursiv, cum am face la un limbaj functional (in stil lisp). Cum determinam daca un numar este prim fara sa mentinem stare? Putem sa definim o "functie" HasDivisors cu doi parametri, N si K. HasDivisors returneaza true daca vreun numar intre 2 si K il divide pe N. Astfel, un numar este prim daca HasDivisors este true pentru parametrii N si N-1. Putem implementa aceasta idee cu template-uri:
Pentru ca tipurile sunt prin definitie imutabile, nu vom putea face compilatorul sa ruleze algoritmi iterativi - nu avem cum sa il facem sa mentina o stare. Va trebui sa convertim orice lucru iterativ in ceva recursiv, cum am face la un limbaj functional (in stil lisp). Cum determinam daca un numar este prim fara sa mentinem stare? Putem sa definim o "functie" _HasDivisors_ cu doi parametri, $N$ si $K$. HasDivisors returneaza true daca vreun numar intre 2 si $K$ il divide pe $N$. Astfel, un numar este prim daca _HasDivisors_ este true pentru parametrii $N$ si $N-1$. Putem implementa aceasta idee cu template-uri:
== code(c) |
template <int N, int K>
};
==
Prima parte a expresiei din PrimeErrors este doar o asertie la timpul compilarii. Operatia de adunare e folosita doar pentru recursivitate. Din nou, specializarea ne da voie sa definim conditia de oprire a recursivitatii. In final nu mai avem nevoie decat de o instructiune care sa faca compilatorul sa evalueze PrimeErrors:
Prima parte a expresiei din _PrimeErrors_ este doar o asertie la timpul compilarii. Operatia de adunare e folosita doar pentru recursivitate. Din nou, specializarea ne da voie sa definim conditia de oprire a recursivitatii. In final nu mai avem nevoie decat de o instructiune care sa faca compilatorul sa evalueze _PrimeErrors_:
== code(c) |
PrimeErrors<100>::Result x;
'CompileTimeError<false>'
==
Daca filtram doar liniile cu In instantiation of ..., vedem frumos rezultatul dorit:
Daca filtram doar liniile cu In _instantiation of ..._, vedem frumos rezultatul dorit:
== code(c) |
root@slack ~# gcc templates.cpp 2>&1 | grep "In in"

Nu exista diferente intre securitate.

Topicul de forum nu a fost schimbat.