Skip to main content

Advanced C++

Templates

Complete lesson for Templates using LEARNCODEGURU’s 6-level learning model — from basics to advanced practice, with C++ OOP and STL where relevant.

L1

Basics — Templates

Section: Advanced C++. C++ templates — write generic functions and classes once, reuse them for many types (the foundation of the STL).

What are templates?

  • A **template** is a blueprint for a function or class that works with **many types**.
  • You write the logic **once**; the compiler generates the concrete version for each type you use.
  • This is **generic programming** — the foundation of the STL (vector, sort, map, …).
  • Two main kinds: **function templates** and **class templates**.
  • **Real-life:** one cookie cutter, many cookies — same shape, different dough (types).
IdeaMeaning
TemplateBlueprint parameterized by types (or values)
InstantiationCompiler creates a real function/class for a type
Function templateGeneric function, e.g. max(a,b)
Class templateGeneric class, e.g. Box / vector
BenefitReuse + type safety without copy-paste

Why use templates?

  • Avoid rewriting the same function for int, double, string, …
  • Keep **type safety** (unlike void* tricks in C).
  • Enable high-performance generic libraries (STL).
  • Support compile-time polymorphism (static polymorphism).
BenefitWhat you gain
DRY codeOne implementation, many types
Type-safeErrors caught at compile time
PerformanceNo virtual call; often fully inlined
STL powervector, algorithms, smart pointers

Function templates

  • Syntax: template (or template ) before the function.
  • typename and class are equivalent here for type parameters.
  • The compiler **deduces** T from the call arguments in most cases.
  • You can also call with an explicit type: maximum(2, 3.5).
#include <iostream>
using namespace std;

template <typename T>
T maximum(T a, T b) {
    return (a > b) ? a : b;
}

int main() {
    cout << maximum(10, 20) << "\n";       // T = int
    cout << maximum(2.5, 1.5) << "\n";     // T = double
    cout << maximum('a', 'z') << "\n";     // T = char
    cout << maximum<int>(3, 9) << "\n";    // explicit T
    return 0;
}

Class templates

  • A class template defines a family of classes parameterized by type(s).
  • You usually specify the type when creating an object: Box b;.
  • std::vector, std::pair are class templates.
  • Member functions of a class template are themselves templates.
#include <iostream>
#include <string>
using namespace std;

template <typename T>
class Box {
    T value;
public:
    explicit Box(T v) : value(v) {}
    T get() const { return value; }
    void set(T v) { value = v; }
};

int main() {
    Box<int> a(42);
    Box<string> b("hi");
    cout << a.get() << " " << b.get() << "\n";
    return 0;
}

Multiple template parameters

  • Templates can take more than one parameter.
  • Useful for pairs, maps, converters, and mixed-type APIs.
#include <iostream>
#include <string>
using namespace std;

template <typename T, typename U>
class Pair {
public:
    T first;
    U second;
    Pair(T a, U b) : first(a), second(b) {}
};

template <typename T, typename U>
auto addMixed(T a, U b) {
    return a + b; // return type deduced (C++14+)
}

int main() {
    Pair<string, int> p("age", 21);
    cout << p.first << " " << p.second << "\n";
    cout << addMixed(2, 3.5) << "\n";
    return 0;
}

Non-type template parameters

  • Parameters can be **values** known at compile time (e.g. int N), not only types.
  • Classic use: fixed-size arrays, std::array.
#include <iostream>
using namespace std;

template <typename T, int N>
class FixedArray {
    T data[N];
public:
    int size() const { return N; }
    T& operator[](int i) { return data[i]; }
};

int main() {
    FixedArray<int, 5> a;
    a[0] = 10;
    cout << a.size() << " " << a[0] << "\n"; // 5 10
    return 0;
}

Template specialization (intro)

  • **Specialization** customizes a template for a specific type.
  • Full specialization: provide a complete alternate definition for one type.
  • Useful when the generic logic does not fit (e.g. bool, pointers, strings).
#include <iostream>
using namespace std;

template <typename T>
void printType() {
    cout << "generic\n";
}

template <>
void printType<int>() {
    cout << "int specialization\n";
}

int main() {
    printType<double>(); // generic
    printType<int>();    // int specialization
    return 0;
}

Templates vs overloading vs macros

  • Overloading: several named functions — fine for a few types.
  • Templates: one definition for unlimited types.
  • Macros: text substitution — no type safety; prefer templates.
ApproachType-safe?Scales to many types?
Manual overloadsYesNo (tedious)
Function templateYesYes
#define macroNoRisky
Virtual / inheritanceYesRuntime polymorphism

Key points to remember

  • Templates generate code **at compile time** for each used type.
  • Function templates often deduce T; class templates usually need Class.
  • typename ≈ class for type parameters.
  • STL is built on templates — learning them unlocks the library.
  • Errors in templates can look noisy — read the “first” error carefully.
  • Put templates in headers (definitions needed where they are used).
L2

Advanced — Templates

Where to put template code

  • The compiler must see the full template definition to instantiate it.
  • Common pattern: define templates in .h / .hpp (or header-only libraries).
  • Explicit instantiation in a .cpp is an advanced alternative.

Default template arguments

  • Class (and function) templates can have defaults, like function parameters.
  • Example idea: template> class vector.
template <typename T = int>
class Number {
    T value = 0;
public:
    T get() const { return value; }
};

Number<> n;        // T = int
Number<double> d;  // T = double

Partial specialization (overview)

  • Class templates can be **partially** specialized (e.g. for pointers T*).
  • Function templates use overloads / full specialization more often than partial specialization.
  • Deeper details appear when you write advanced container-like types.
template <typename T>
struct TypeName { static void show() { /* generic */ } };

template <typename T>
struct TypeName<T*> { // partial: pointers
    static void show() { /* pointer case */ }
};

Templates and compile-time polymorphism

  • Calling maximum(a,b) selects/generates the right code at **compile time**.
  • No vtable needed — often faster than virtual dispatch for generic utilities.
  • Trade-off: code size can grow (one copy per type used).

Common pitfalls

  • Mixed argument types may fail deduction: maximum(2, 3.5) — fix with casts or two parameters.
  • Huge error messages — scroll to the first “required from here”.
  • Do not put non-inline template definitions only in a .cpp without explicit instantiation.
// Deduction problem:
// maximum(2, 3.5); // error: T cannot be both int and double

template <typename T, typename U>
auto maximum2(T a, U b) {
    return (a > b) ? a : b;
}

STL connection

  • vector, map, sort, unique_ptr — all templates.
  • Algorithms take iterator types deduced as template parameters.
  • Understanding templates makes STL headers less mysterious.
L3

Tricky Interview Points

Q1) What is a template in C++?

Answer A blueprint for a function or class parameterized by types (or values) that the compiler instantiates for each use.

Q2) Function template vs class template?

Answer Function templates define generic functions (often with argument deduction). Class templates define generic types like Box<T> or vector<T>.

Q3) typename vs class in template parameters?

Answer For type parameters they are equivalent. typename is also used to mark dependent type names inside templates.

Q4) What is template instantiation?

Answer The compiler generating a concrete function or class from a template for specific template arguments.

Q5) What is template specialization?

Answer Providing a custom implementation of a template for a particular type (or pattern of types).

Q6) Why are templates usually in headers?

Answer The definition must be visible at the point of instantiation so the compiler can generate code.

Q7) How do templates relate to the STL?

Answer STL containers and algorithms are templates — generic, type-safe, and compile-time generated.

Q8) Can template parameters be values?

Answer Yes — non-type parameters such as int N in array<T, N>.

Q9) Templates vs macros?

Answer Templates are type-checked and scoped; macros are text substitution and error-prone.

Q10) What is compile-time polymorphism?

Answer Selecting/generating behaviour at compile time via overloads and templates, as opposed to runtime virtual dispatch.

Q11) Why might maximum(2, 3.5) fail?

Answer A single T cannot deduce as both int and double. Use explicit casts, explicit <double>, or two type parameters.

Q12) Give a real-life analogy for templates.

Answer A cookie cutter (template) producing many cookies (instantiations) from different dough (types).

L4

Simple Programs

Function template — maximum

#include <iostream>
using namespace std;

template <typename T>
T maximum(T a, T b) {
    return (a > b) ? a : b;
}

int main() {
    cout << maximum(4, 9) << "\n";
    cout << maximum(2.7, 2.2) << "\n";
    return 0;
}

Function template — swap

#include <iostream>
using namespace std;

template <typename T>
void mySwap(T& a, T& b) {
    T t = a; a = b; b = t;
}

int main() {
    int x = 1, y = 2;
    mySwap(x, y);
    cout << x << " " << y << "\n";
    string a = "hi", b = "bye";
    mySwap(a, b);
    cout << a << " " << b << "\n";
    return 0;
}

Class template — Stack

#include <iostream>
#include <vector>
using namespace std;

template <typename T>
class Stack {
    vector<T> data;
public:
    void push(const T& x) { data.push_back(x); }
    void pop() { if (!data.empty()) data.pop_back(); }
    T top() const { return data.back(); }
    bool empty() const { return data.empty(); }
};

int main() {
    Stack<int> s;
    s.push(10); s.push(20);
    cout << s.top() << "\n";
    return 0;
}

Non-type parameter — FixedArray

#include <iostream>
using namespace std;

template <typename T, size_t N>
void printAll(const T(&arr)[N]) {
    for (size_t i = 0; i < N; ++i) cout << arr[i] << " ";
    cout << "\n";
}

int main() {
    int a[] = {1, 2, 3, 4};
    printAll(a);
    return 0;
}

Full specialization example

#include <iostream>
#include <cstring>
using namespace std;

template <typename T>
int mySize(T) { return sizeof(T); }

template <>
int mySize<const char*>(const char* s) {
    return (int)strlen(s);
}

int main() {
    cout << mySize(3.14) << "\n";
    cout << mySize("hello") << "\n";
    return 0;
}

Two-parameter template

#include <iostream>
using namespace std;

template <typename A, typename B>
void showPair(A a, B b) {
    cout << a << " , " << b << "\n";
}

int main() {
    showPair(1, "one");
    showPair(3.5, 10);
    return 0;
}
L5

Problem Solving Tricks

  • template before function or class.
  • Function templates deduce T; class templates need Class.
  • typename and class are the same for type parameters.
  • STL = templates everywhere.
  • Put template definitions in headers.
  • Specialization customizes one type’s behaviour.
  • Non-type params: sizes and compile-time constants.
  • maximum(2, 3.5) often fails — types must match one T.
  • Templates = compile-time / static polymorphism.
  • Prefer templates over macros for generics.
  • Read the first compiler error in a template blast.
  • Cookie-cutter analogy works well in interviews.
L6

Practice Programs List

  1. Write a template min(a,b) and test with int and double.
  2. Implement a class template Pair with a print() method.
  3. Write mySwap as a function template for two references.
  4. Build a simple Stack with push/pop/top using vector.
  5. Create FixedArray and print N.
  6. Specialize a printType template for int and for string.
  7. Show a deduction failure with maximum(1, 2.5) and fix it.
  8. Write a template function that prints any array with size N.
  9. List five STL templates you already use.
  10. Explain in comments why templates live in headers.
  11. Add a default template argument to a small class template.
  12. Compare templates vs function overloading in a short table.