Rešio sam da napišem jedan tekstić koji će ohrabriti C++ programere da se pozabave upotrebom šablona (engl. templates) pri izradi programa. Tekst ću premijerno objaviti na ES-u, a ako neko želi da ga iskopira i prikaže na nekom drugom mestu, ima moj blagoslov za to.
Tekst je namenjen ljudima koji poznaju C++, ali nisu radili sa šablonima. Namera mi je da naučim ljude da koriste biblioteke zasnovane na šablonima (pre svega STL), a ne da pišu takve biblioteke. Dakle, izostaviću mnoge "napredne" teme rada sa šablonima, kao što je meta-programiranje, liste tipova, itd i zadržaću se na osnovnim stvarima. Ako bude interesovanja, možda napišem i nastavak koji bi išao više "u dubinu".
1. Šta su šabloni?
U programerskoj praksi je jedan od najznačajnijih pitanja, kako napisati kod koji se može koristiti za rešavanje što više praktičnih problema (tzv "code reuse"). Tako se došlo do zaključka da mnogi algoritmi izgledaju praktično isto kada rade sa različitim tipovima. Uzmimo sasvim jednostavan primer: funkciju max koja treba da vrati veću (u stvari "ne manju") od dve zadate vrednosti. Za celobrojne bojeve, ova funkcija bi izgledala ovako:
const int& max (const int& a, const int& b)
{
return a > b ? a : b;
}
A ako bismo hteli da napravimo istu funkciju za realne brojeve, dobili bismo nešto ovako:
const double& max (const double& a, const double& b)
{
return a > b ? a : b;
}
Ili ako imamo klasu "titula" za koju je preklopljen operator >
const titula& max (const titula& a, const titula& b)
{
return a > b ? a : b;
}
U čemu se razlikuju ove tri funkcije? Jedino u tipu argumenata i povratne vrednosti. Kada bismo mogli da i tip prosledimo kao argument funkcije, onda bismo imali jednu funkciju koja radi sa svim tipovima koji "prepoznaju" operator >. Upravo tu dolaze šabloni kao rešenje za naš problem:
template <typename T>
const T& max (const T& a, const T& b)
{
return a > b ? a : b;
}
Ovde je T tip - int, double, titula ili ma koji drugi za koji postoji operator >. Šablon funkcija koju smo upravo definisali, strogo gledano, nije obična funkcija koja prihvata dodatni parametar za tip promenljivih, već upravo to što mu ime kaže: šablon na osnovu koga kompajler može da napravi potencijalno bezbroj funkcija koje se razlikuju samo po tipu. Osim šablon funkcija, postoje i šablon klase, koje se često koriste kao "kontejneri" za različite tipove. Tipičan primer takve šablon klase je STL klasa vector, koja se često koristi umesto C++ nizova.
Kako se u praksi koriste šabloni? Evo jednostavnog primera:
template <typename T>
const T& max (const T& a, const T& b)
{
return a > b ? a : b;
}
#include <vector>
int main (void)
{
std::vector<int> niz;
niz.push_back(1);
niz.push_back(2);
niz.push_back(3);
int m = max<int> (niz[1], niz[2]);
}
Najpre smo definisali promenljivu niz kao vector<int>; onda smo joj dodali 3 cela broja, i na kraju smo promenljivoj m dodelili vrednost većeg od poslednja dva elementa u niz-u. Najpre smo vector-u naznačili da treba da sadrži promenljive tipa int, a kasnije smo i funkciji max naznačili da radi sa promenljivama tipa int (kod šablon funkcija, ovo često nije potrebno činiti, jer je kompajler dovoljno pametan da sam zaključi o kom se tipu radi - o tome nešto više kasnije). Kada bismo recimo umesto sa int-ovima, radili sa dooble-ovima, kod bi izgledao ovako:
std::vector<double> niz;
niz.push_back(1.);
niz.push_back(2.);
niz.push_back(3.);
double m = max<double> (niz[1], niz[2]);
Dakle, nismo morali da menjamo kod unutar funkcije max ili klase vector, već smo samo iskoristili šablone da dobijemo tipove koji rade sa double, umesto sa int.
Nastavak sledi...
[Ovu poruku je menjao Dragi Tata dana 20.12.2002. u 10:30 GMT]