﻿
#include <iostream>
using namespace std;

// dzięki generycznemu szablonowi klasy można zdefiniować wiele klas w zależności od typów danych


//definicja szablonu klasy Dodawanie wersja ogólna (generyczna)
template <typename T>
class Dodawanie {
private:
    T a;
    T b;
public:
    // konstruktor
    Dodawanie(T aa, T bb) : a(aa), b(bb) {};
    T dodaj();
};

// definicja szablonu specjalizowanego klasy Dodawanie, parametrem szablonu jest typ char
// definicja różni się od wersji generycznej
template <>
class Dodawanie <char> {
private:
    char a;
    char b;
public:
    // konstruktor
    Dodawanie(char aa, char bb) : a(aa), b(bb) {};
    char dodaj() {
        cout << "dodajemy kody ASCII znaków:\n'"<< a << "' - kod " << (int)a << endl <<"'"<< b <<
             "' - kod " << (int)b << "\ni zwracamy znak, którego kodem jest otrzymana suma\n" << 
            "kod (suma) " << (int)a + (int)b << ": ";
        return a + b;
    };
};

int main()
{
    // przy tworzeniu obiektu na podstawie szablonu klasy 
    // kompilator w pierwszej kolejności szuka specjalizacji szablonu dla podanego typu, 
    // gdy jej nie znajdzie konkretyzuje szablon dla tego typu.

    
    // Kompilator generuje klasę na podstawie szablonu
    // - instancję szablonu skonkretyzowaną dla
    // podanego w nawiasach kwadratowych typu danych, 
    // na podstawie tak wygenerowanej klasy powstaje obiekt.
    Dodawanie <int> dwieLiczby(10, 20);
    cout << dwieLiczby.dodaj() << endl;

    // Gdy znajdzie specjalizację szablonu klasy dla podanego typu
    // tworzy obiekt korzystając ze znalezionej specjalizacji
    Dodawanie <char> dwaZnaki('1', '0');
    cout << dwaZnaki.dodaj() << endl;
}

// definicja metody dodaj()
template<typename T>
T Dodawanie<T>::dodaj()
{
    return a + b;
}

