Przykład zawiera następujące zagadnienia: szablony funkcji, funkcje specjalizowane, szablony klas, funkcje zaprzyjaźnione, specjalizowana klasa szablonowa, zmienne statyczne w szablonach klas, dynamiczne obiekty szablonowe.

Kod jest uzupełniony o komentarze które przydadzą się w trakcie jego analizy. Kompilowane pod Visual Studio 2010.



// szablony.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <string>

using namespace std;

// zwykła funkcja
void porownaj(int a, int b)
{
if(a > b)
{
cout<<a<<" jest wieksze od "<<b<<endl;
}
else if(a == b)
{
cout<<a<<" jest rowne "<<b<<endl;
}
else
{
cout<<a<<" jest mniejsze od "<<b<<endl;
}
}

// szablony funkcji nalezy umieszczac w zakresie globalnym
template <class mojtyp>
void porownaj2(mojtyp a, mojtyp b)
{
if(a > b)
{
cout<<a<<" jest wieksze od "<<b<<endl;
}
else if(a == b)
{
cout<<a<<" jest rowne "<<b<<endl;
}
else
{
cout<<a<<" jest mniejsze od "<<b<<endl;
}
}

// funkcja specjalizowana
void porownaj2(int a, double b)
{
cout<<"int: "<<a<<", double: "<<b<<endl;
}

//========================================================

//szablon klasy
template <class mojtyp>
class TSchowek
{
private:
mojtyp Schowek;
public:
static int Licznik;

TSchowek()
{
Licznik++;
}

void setSchowek(mojtyp arg)
{
Schowek = arg;
}

mojtyp getSchowek()
{
return Schowek;
}

//deklaracja metody
void setSchowekAndPrint(mojtyp);

// funkcja zaprzyjazniona
// wymagane jest podanie template <class mojtyp> aby funkcja zaprzyjazniona miała faktycznie dostep do prywatnych skladnikow klasy
template <class mojtyp> friend void inspektor(TSchowek<mojtyp> &);
};

// szablon metody zdefinowany na zewnątrz klasy
template <class mojtyp>
void TSchowek<mojtyp>::setSchowekAndPrint(mojtyp arg)
{
Schowek = arg;
cout<<"Ustawiono schowek: "<<arg<<endl;
};

// ustawiamy licznik statyczny na 0. Przypisanie do zmiennej statycznej musi odbywać się na zewnątrz klasy
template <class mojtyp>
int TSchowek<mojtyp>::Licznik = 0;

// definicja funkcji zaprzyjaznionej z klasa TSchowek
// funkcja zaprzyjaźniona musi być funkcją szablonową
template <class mojtyp>
void inspektor(TSchowek<mojtyp> & obj)
{
// pobieramy wartosc prywatnej zmiennej klasy dzięki temu, że jest to funkcja zaprzyjaziona
cout<<"Prywatny składnik schowek: "<<obj.Schowek;
}

// specjalizowana klasa szablonowa
template <> // wymagane jest wpisanie: template <>
class TSchowek<char>
{
private:
char Schowek;
public:
static int Licznik;

TSchowek()
{
Licznik++;
}

void setSchowek(char arg)
{
Schowek = arg;
cout<<"Ustawiono schowek na char: "<<arg;
}
};

// ustawienie zmiennej statycznej
int TSchowek<char>::Licznik = 0;

//========================================================

int _tmain(int argc, _TCHAR* argv[])
{

porownaj(3.5,3); // w wyniku da 3 jest rowne 3

porownaj2<double>(3.5,3); // 3.5>3

porownaj2<char>('c','b'); // c>b

// nie trzeba podwac <double> poniewaz na podstawie typu argumentow tworzona jest funkcja z szablonu
porownaj2(12.1,19.54); // 12.1 < 19.54

// zostanie uzyta funkcja specjalizowana poniewaz pierwszy argument to int a drugi double
// (zgodnie z definicja funkcji specjalizowanej gdzie argumenty to int,double)
porownaj2(3,4.2);

// Tutaj tez uruchomi sie funkcja specjalizowana mimo ze jako pierwszy typ podalismy double, a nie int.
// Jest to spowodowane typ ze argumenty roznia sie typami a w szablonie oba argumenty powinny byc takie same by moglby byc uzyte
// Jako drugi argument podalismy int zamiast double.
// Funkcja zwroci double:3, int:3
// W pierwszym argumencie 3.5 zostanie zamienione na 3 bo ten argument ma byc typu int
porownaj2(3.5,3);

//tez zostanie uzyta funkcja specjalizowana
porownaj2('a',3); //zwroci int: 97, double: 3

cout<<"--------------n";

cout<<"nObiekty TSchowek<int>n";

TSchowek<int> obj;

obj.setSchowek(20);
cout<<"Schowek: "<<obj.getSchowek()<<"n";
cout<<"Licznik statyczny: "<<obj.Licznik<<"n";

TSchowek<int> obj2;
obj2.setSchowekAndPrint(34);
cout<<"Licznik statyczny: "<<obj2.Licznik<<"n"; // wyświetli 2 bo utworzyliśmy dotychczas dwa obiekty typu TSchowek<int>

inspektor<int>(obj2); // wywołanie funkcji zaprzyjaźnionej z klasą TSchowek

cout<<"nObiekty TSchowek<string>n";

TSchowek<string> obj_string1;

obj_string1.setSchowek("Jakis tekst :)");
cout<<"Schowek: "<<obj_string1.getSchowek()<<"n";

obj_string1.setSchowekAndPrint("Nowy tekst");

cout<<"Licznik statyczny: "<<obj_string1.Licznik<<"n";

TSchowek<string> obj_string2;
cout<<"Licznik statyczny: "<<obj_string2.Licznik<<"n";
TSchowek<string> obj_string3;
// Licznik przechowuje liczbę utworzonych obiektów których typ to TSchowek<string>
// Utworzyliśmy 3 obiekty więc licznik wyświetli liczbę 3
cout<<"Licznik statyczny: "<<obj_string3.Licznik<<"n";



cout<<"nDynamiczne obiekty szablonowen";

// dynamiczne obiekty szablonowe
TSchowek<double> *wsk = new TSchowek<double>;
wsk->setSchowek(3.234);
cout<<"Schowek: "<<wsk->getSchowek()<<"n";
cout<<"Licznik statyczny: "<<wsk->Licznik<<"n"; // licznik wyświetli 1 bo utworzyliśmy tylko jeden obiekt typu TSchowek<double>
delete wsk;

TSchowek<double> *wsk2 = new TSchowek<double>;
wsk2->setSchowek(3.234);
cout<<"Schowek: "<<wsk2->getSchowek()<<"n";
cout<<"Licznik statyczny: "<<wsk2->Licznik<<"n"; // licznik wyświetli 2 bo utworzyliśmy drugi obiekt typu TSchowek<double>
delete wsk2;

TSchowek<double> obj_double;
cout<<"Licznik statyczny: "<<obj_double.Licznik<<"n"; // licznik wyświetli 3 poniewaz utworzylismy trzeci obiekt typu TSchowek<double> mimo, że nie jest on oparty na wskazniku. Liczy się typ utworzonego obiektu!

cout<<"nObiekty TSchowek<char> (specjalizowana klasa szablonowa)n";
TSchowek<char> obj_char;
obj_char.setSchowek('F');

cout<<"nn";
system("pause");
return 0;
}