It is currently Fri Sep 10, 2010 11:36 am




Post new topic Reply to topic  [ 2 posts ] 
[Tutorial] Functii template 
Author Message
C++ fan
User avatar

Joined: Sat Jan 03, 2009 1:42 am
Posts: 247
Location: http://bitcell.info
Post [Tutorial] Functii template
Autor: Razzor
Corectari: Astan

I Functii template

Acesta este un tutorial despre functii template urmand sa fac cat de curant unul despre clase template.

1.1 Sintaxa and other
Functile template reprezinta o familie de functii.

Ele arata ca si o functie normala cu exceptia unor elemente care le vom explica.Urmatoarea functie template returneaza maximul dintre doua valori:
Code:

template <typename T>
const T&  maxim (const T&  a, const T&  b)
{
    //Daca a<b returneaza b, altfel returneaza a
    return a < b ? b : a;
}



Aceasta definitie produce o familie de functii care returneaza maximul a doua valori care sunt pasate prin intermediul parametrilor a si b.Tipul acestor parametrii este lasat liber cu un parametru template T.

Dupa cum am vazut in exemplu, parametrii template trebuie sa fie anuntati cu o syntaxa de genul :
Code:

template < lista_de_parametrii_separata_prin_virgule >



In exemplul nostru lista de parametrii continea doar un parametru si anume typename T.Observam de asemenea semnul mai mic si mai mare, acestea au rolul de paranteze unghiulare.Observam si cuvantul cheie typename care este folosit pentru a defini tipul parametrilor.Din motive istorice se poate folosit si class in loc de typename.Cuvantul cheie typename a fost introdus relativ recent in evolutia limbajului c++.
Se prefera folosirea cuvantului typename deoarece cuvantul class poate induce in eroare iar intre ele nu exista practic nici o diferenta.

Urmatorul cod prezinta folosirea acestei functii template:

Code:
#include <iostream>
#include <string>

using namespace std;

//functia template
template <typename T>
const T&  maxim (const T&  a, const T&  b)
{
    return a < b ? b : a;
}

int main()
{
    int i = 42;
    int j = 34;
    cout << "int max "<<maxim(i,j)<<endl;

    double d1 = 3.4;
    double d2 = -6.7;
    cout << "double max " << maxim(d1,d2) <<endl;

    string s1 = "ilea";
    string s2 = "cristian";
    cout << "string max " << maxim(s1,s2) <<endl;

    return 0;
}


In acest program, functia maxim() este apelata de 3 ori.Odata pentru doua int-uri apoi pentru doua double-uri si apoi pentru doua string-uri.De fiecare data maximul este determinat iar programul afiseaza urmatoarele:
Code:
int max 42
double max 3.4
string max ilea


Functiile template nu sunt compilate in entitati singulare care sa poata primi orice tip ca parametru.In schimb se genereaza entitati diferite din template pentru fiecare tip pentru care functia template este folosita.Sa luam ca exemplu prima apelare a lui maxim().
Code:
int i = 42;
int j = 34;
cout << "int max "<< maxim(i,j) << endl;


Acesti prim apel foloseste functia template cu int ca si parametru in loc la T.Codul echivalent pentru aceasta functie este:
Code:
const int& maxim (const int&  a, const int&  b)
{
    return a < b ? b : a;
}


Procesul de a inlocui parametrii template cu tipuri concrete se numeste instantiere.Similar cu apelul lui maxim() pentru int asa se instantiaza si pentru double sau string:
Code:
const double& maxim (const double& d1, const double& d2); {/* ... */}
const string& maxim (const string& s1, const string& s1); {/* ... */}


1.2Deducerea parametrilor

Cand se apeleaza o functie template ca si maxim() , pentru unele cazuri, parametrii template sunt determinati in functie de argumentele care le pasam.Daca pasam doua int-uri parametrului T , compilatorul C++ trebuie sa concluzioneze ca T trebuie sa fie int.De retinut faptul ca nu este permisa conversia de tip.T trebuie sa se potriveasca exact.
De exemplu:
Code:
template <typename T>
const T& maxim (const T& a, const T& b);
/* ..cod..  */
maxim(4,7)     // OK: T este int pentru amandoua argumentele
maxim(4,4.2)   // Eroare: primul T este int apoi al doilea este double

Putem rezolva aceasta eroare in 2 moduri:

1.Putem folosi operatorul static_cast <tip_de_conversie> (variabila_de_convertit)
Code:
maxim(static_cast<double>(4),4.2)

Astfel 4 este convertit in double ( 4.0 ) iar T este double pentru amandoua argumentele.

2.Specificam explicit tipul lui T
Code:
maxim<double>(4,4.2)



Functile template au doua tipuri de parametrii:

1.Parametrii template care sunt declarati intre paranteze unghiulare inaintea numelui functiei template.

Code:
template <typename T>      //T este parametru template


2.Parametrii de apelare care sunt declarati in paranteze rotunde dupa numele functiei template
Code:
const T& maxim (const T&  a, const T&  b)         //a si b sunt parametrii de apelare

Puteti sa aveti cat de multi parametrii template vreti.

Putem defini maxim() cu doi parametrii de apelare de doua tipuri diferite:


Code:
template <typename T1, typename T2>
T1 maxim (const T1& a, const T2&  b)
{
    return a < b ? b : a;
}
/* ...cod... */
maxim(4,4.2)   // e ok, dar tipul primului argument defineste tipul care va fi returnat


Aceasta pare o metoda buna dar are acest exemplu are si parti proaste.Problema este ca tipul de returnare trebuie sa fie declarat.Daca folositi unul din parametrii ca si tip de returnare, argumentul celuilalt parametru va fi convertit in in tipul primului , in ciuda intentilor utilizatorului.C++ nu pune la dispozitie un mod de a specifica "cel mai puternic tip" (desi poti sa faci asa ceva cu ajutorul unor tehnici smechere de template programming care poate o sa le prezint in alt tutorial).Deci depinde de argumentul cu care se face apelarea.Maximul dintre 42 si 66.66 poate sa fie double 66.66 sau int 66.

Putem sa introducem un al treilea argument template pentru a defini tipul de care il va returna functia template:

Code:
template <typename T1, typename T2, typename RT>
RT maxim (const T1&  a, const T2&  b);

Totusi RT nu poate fi dedus.Ca o consecinta , noi trebuie sa specificam lista de argumente in mod explicit
Code:
template <typename T1, typename T2, typename RT>
RT maxim (const T1&  a, const T2&  b);
maxim<int,double,double>(4,4.2)   //ok, dar cam aiurea


Putem sa rearanjam parametrii template pentru ca restul sa fie deduse in mod automat:
Code:
template <typename RT, typename T1, typename T2>   //observati asezarea
RT maxim (const T1& a, const T2&  b);
/* ... code ... */
maxim<double>(4,4.2)    // ok, tipul pe care in returneaza maxim() este double



In acest exemplu , apelul maxim<double> seteaza RT ca fiind explicit double, dar parametri T1 si T2 sunt dedusi ca fiind int si double.


1.3Supraincarcarea functilor template

Ca si functile normale , functile template pot fi supraincarcate.Adica poti avea diferite definitii de functii cu acelasi nume si atunci cand un numele este folosit in apelarea functiei , compilatorul c++ trebuie sa decida care din candidati(definitii) sa aleaga.Regulile folosite pentru a decide ce definitie sa fie folosita pot deveni oarecum complicate chiar si fara temaplateuri.Mai jos vom discuta despre supraincarcarea functilor template.
Code:
//maximul a doua valori int
const int& maxim (const int& a, const int& b)
{
    return a < b ? b : a;
}

//maximul dintre doua valori de orice tip
template <typename T>
const T& maxim (const T& a, const T& b)
{
    return a < b ? b : a;
}
//maximul dintre 3 valori de orice tip
template <typename T>
const T& maxim (const T& a, const T& b, const T& c)
{
    return maxim (maxim(a,b), c);
}

int main()
{
    maxim(7, 42, 68);     //1 apeleaza functia template pentru 3 argumente
   
    maxim(7.0, 42.0);     //2 apeleaza maxim<double> (prin deductie de argument)
   
    maxim('a', 'b');      //3 apeleaza maxim<char> (prin deductie de argument)
   
    maxim(7, 42);         //4 apeleaza functia nontemplate pentru doua valori int
   
    maxim<>(7, 42);       //5 apeleaza maxim<int> (prin deductie de argument)
   
    maxim<double>(7, 42); //6 apeleaza maxim<double> (fara deductie de argument , noi i-am impus ce sa foloseasca)
   
    maxim('a', 42.7);     //7 apeleaza functia nontemplate pentru doua valori int

    return 0;
}



Dupa cum vedem in exemplul de mai sus , o functie nontemplate poate sa coexiste cu functii template care au acelasi nume.Procesul de supraincarcare prefera functia nontemplate.Al patrulea apel cade sub aceasta regula.
Code:
maxim(7, 42);  // amandoua valorile se incadreaza perfect in functia nontemplate


Daca templateul poate genera o functie care sa se potriveasca mai bine, compilatorul alege functia template.Acest lucru este demonstrat de al 2-lea si al 3-lea apel:
Code:
maxim(7.0, 42.0);     // apeleaza maxim<double> (prin deductie de argument)
   
maxim('a', 'b');      // apeleaza maxim<char> (prin deductie de argument)
   

Este posibil sa pasam o lista fara argumente template.Aceasta sintaxa spune compilatorului ca doar o functie template poate sa rezolve acel apel dar toti toti parametrii template trebuie dedusi din tipul argumentelor cu care apelam functia.
Code:
maxim<>(7, 42)    //doar functia nontemplate poate primi argumente de tip diferit


Deoarece conversia de tip nu este posibila pentru functile template, ultimul apel foloseste functia nontemplate (iar vlorile 'a' si 42,7 sunt convertite in int)


Sun Aug 23, 2009 2:12 pm
Profile
Braincode Programmer
User avatar

Joined: Mon Jan 14, 2008 3:24 am
Posts: 363
Location: Calarasi
Post Re: [Tutorial] Functii template
Nu am citit totul pt ca nu am timp dar ce m-am uitat in mare asa pare bine formulat. bravo e bine ca mai sunt cattiva care isi dau silinta sa mai invete si pe altii


Sun Aug 23, 2009 7:22 pm
Profile
 
Post new topic Reply to topic  [ 2 posts ] 


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  
Powered by phpBB © phpBB Group.
Designed by boogiesbc and Vjacheslav Trushkin .