Šabloni (template) u C++-u

Lekcija 18 od 18 · C++

Kako napisati jednu funkciju koja radi i sa int, i sa double, i sa string? Pomoću šablona: tip postaje parametar, a prevodilac sam pravi verziju za svaki tip koji se koristi. Na ovaj način su napravljeni vector, sort i ceo STL.

Pre nego što počneš: potrebno predznanje – nasleđivanje, STL.
Kako da učiš: svaki primer prekucaj i pokreni, a zadatke na kraju prvo reši sam/a; uputstvo i rešenje otvori tek posle toga. Svi programi su u C++-u (C++17) i provereno se prevode i daju navedeni izlaz.

Šablonska funkcija

#include <bits/stdc++.h>
using namespace std;

template <typename T>                     // T je "bilo koji tip"
T najveci(const vector<T>& v) {
    T m = v[0];
    for (const T& x : v)
        if (m < x) m = x;                 // T mora da podržava operator <
    return m;
}

template <typename T>
void ispisi(const vector<T>& v) {
    for (size_t i = 0; i < v.size(); i++)
        cout << v[i] << (i + 1 < v.size() ? ", " : "\n");
}

int main() {
    vector<int> brojevi = {4, 9, 2};
    vector<double> visine = {1.62, 1.75, 1.58};
    vector<string> imena = {"Mila", "Ana", "Teodora"};
    cout << najveci(brojevi) << " " << najveci(visine) << " " << najveci(imena) << "\n";
    ispisi(imena);
    return 0;
}

Prevodilac na osnovu argumenta sam zaključi T (int, double, string) i napravi tri verzije funkcije. Najveći string je „Teodora“, jer se stringovi porede abecedno (T dolazi posle M i A).

Šablonska klasa: sopstveni stek

#include <bits/stdc++.h>
using namespace std;

template <typename T>
class Stek {
    vector<T> podaci;
public:
    void push(const T& x) { podaci.push_back(x); }
    void pop() { podaci.pop_back(); }
    T& top() { return podaci.back(); }
    bool empty() const { return podaci.empty(); }
    size_t size() const { return podaci.size(); }
};

int main() {
    // provera zagrada: ( [ { } ] ) – ispravno, ( ] – neispravno
    string s;
    cin >> s;
    Stek<char> st;                         // ista klasa, tip char
    bool ok = true;
    for (char c : s) {
        if (c == '(' || c == '[' || c == '{') st.push(c);
        else {
            char ocekivano = c == ')' ? '(' : c == ']' ? '[' : '{';
            if (st.empty() || st.top() != ocekivano) { ok = false; break; }
            st.pop();
        }
    }
    cout << (ok && st.empty() ? "ISPRAVNO" : "NEISPRAVNO") << "\n";
    return 0;
}

Pri korišćenju šablonske klase tip se navodi u uglastim zagradama: Stek<char>, Stek<int> – kao vector<int>. Stek je detaljno objašnjen u lekciji Stek.

Više parametara i auto

#include <bits/stdc++.h>
using namespace std;

template <typename K, typename V>
V vrednostIliPodrazumevano(const map<K, V>& m, const K& kljuc, const V& podrazumevano) {
    auto it = m.find(kljuc);
    return it == m.end() ? podrazumevano : it->second;
}

int main() {
    map<string, int> bodovi = {{"Ana", 95}, {"Iva", 80}};
    cout << vrednostIliPodrazumevano(bodovi, string("Ana"), 0) << " "
         << vrednostIliPodrazumevano(bodovi, string("Luka"), 0) << "\n";

    auto zbir = [](auto a, auto b) { return a + b; };   // "šablonska" lambda (C++14)
    cout << zbir(2, 3) << " " << zbir(1.5, 2.25) << " " << zbir(string("ab"), string("cd")) << "\n";
    return 0;
}
ZapisZnačenje
template <typename T>šablon sa jednim tipom (može i class T – isto je)
template <typename K, typename V>više tipova
template <typename T, int N>i broj može biti parametar (npr. array<int, 5>)
auto u lambdikraći način za jednostavne šablonske funkcije

Zadaci za vežbu

Za svaki zadatak postoji primer, uputstvo i rešenje. Rešenja su provereno tačna na primerima iz teksta.

ZADATAK 01Težina: lako

Brojanje većih od proseka

Napiši šablonsku funkciju vecihOdProseka(const vector<T>& v) koja vraća koliko elemenata je strogo veće od proseka. Učitati n celih brojeva, pa m realnih i ispisati oba rezultata.

Primer

Ulaz

5
1 2 3 4 5
3
1.5 2.5 10.0

Izlaz

2 1
Česte greške i saveti
  • Šablon se piše ceo u zaglavlju (.h) ili istom fajlu – prevodilac mora da vidi kod da bi napravio verziju za novi tip.
  • Greške u šablonima su duge i nečitke; traži prvi red koji pominje tvoj fajl i red.
  • Tip mora da podržava sve operacije iz šablona (npr. < za najveci) – inače greška pri prevođenju.

Proveri znanje

Otvori kviz

Šabloni

1. Šta je T u template <typename T>?




2. Kako se pravi objekat šablonske klase Stek za cele brojeve?




3. Koji deo STL-a NIJE šablon?