Programming Language & Its Applications β Generic Programming and Exception Handling, NEC licence examination syllabus (Nepal Engineering Council).
Write the algorithm once, let the compiler generate a version for every type you use it with.
std::sort can sort a vector of ints, a vector of strings, or a vector of your own class with the same source code and no speed penalty β the compiler generates a separate, fully-optimised function for each. That is fundamentally different from Java generics, which erase the type at compile time and box everything, and from Python, which checks types at runtime. C++ templates cost nothing at runtime and everything at compile time, which is exactly why C++ builds are slow and C++ binaries are fast. Search "C++ templates vs Java generics type erasure" β the comparison explains a surprising amount about both languages.#include <iostream>
#include <string>
#include <typeinfo>
/* one type parameter */
template <typename T>
T maximum(T a, T b) { return a > b ? a : b; }
/* two type parameters β a and b may differ */
template <typename T, typename U>
void showPair(const T &a, const U &b) {
std::cout << " (" << a << ", " << b << ")\n";
}
/* return type deduced from the expression (C++11 trailing,
C++14 plain auto) */
template <typename T, typename U>
auto add(T a, U b) -> decltype(a + b) { return a + b; }
/* a NON-TYPE parameter: N is a compile-time constant */
template <typename T, int N>
T sumArray(const T (&arr)[N]) {
T s = T{}; /* zero-initialise */
for (int i = 0; i < N; i++) s += arr[i];
return s;
}
/* template with a default type argument */
template <typename T = double>
T half(T v) { return v / T(2); }
int main() {
std::cout << " maximum(3, 7) = " << maximum(3, 7) << "\n";
std::cout << " maximum(2.5, 1.5) = " << maximum(2.5, 1.5) << "\n";
std::cout << " maximum('a', 'z') = " << maximum('a', 'z') << "\n";
std::cout << " maximum(str) = "
<< maximum(std::string("apple"),
std::string("banana")) << "\n";
/* deduction FAILS with mixed types on one parameter */
/* maximum(3, 7.5); error: deduced conflicting types
for 'T' ('int' vs 'double') */
std::cout << " maximum<double>(3, 7.5) = "
<< maximum<double>(3, 7.5) << " (forced)\n";
showPair(101, "Ram");
showPair(3.14, 'x');
std::cout << " add(3, 4.5) = " << add(3, 4.5)
<< " (type " << typeid(add(3, 4.5)).name() << ")\n";
int ia[] = {10, 20, 30, 40, 50};
double da[] = {1.5, 2.5, 3.5};
std::cout << " sumArray(int[5]) = " << sumArray(ia) << "\n";
std::cout << " sumArray(double[3]) = " << sumArray(da) << "\n";
std::cout << " half(7) = " << half(7)
<< " (T=int, integer division!)\n";
std::cout << " half<double>(7) = " << half<double>(7) << "\n";
return 0;
}
Output:
maximum(3, 7) = 7
maximum(2.5, 1.5) = 2.5
maximum('a', 'z') = z
maximum(str) = banana
maximum<double>(3, 7.5) = 7.5 (forced)
(101, Ram)
(3.14, x)
add(3, 4.5) = 7.5 (type d)
sumArray(int[5]) = 150
sumArray(double[3]) = 7.5
half(7) = 3 (T=int, integer division!)
half<double>(7) = 3.5
half(7) == 3 result is the single most important lesson here. A template is instantiated with whatever the caller passed, so the caller's argument type silently determines your arithmetic. Guarding against it means either forcing the type (half<double>), constraining the template, or computing in a deliberately wider type β never assuming.
#include <iostream>
#include <string>
#include <vector>
/* generic swap β the classic first template */
template <typename T>
void mySwap(T &a, T &b) { T t = a; a = b; b = t; }
/* generic bubble sort over any array */
template <typename T>
void bubbleSort(T arr[], int n) {
for (int i = 0; i < n - 1; i++) {
bool swapped = false;
for (int j = 0; j < n - 1 - i; j++)
if (arr[j] > arr[j + 1]) { /* needs operator> */
mySwap(arr[j], arr[j + 1]);
swapped = true;
}
if (!swapped) return;
}
}
/* generic binary search β requires SORTED input */
template <typename T>
int binarySearch(const T arr[], int n, const T &key, int &steps) {
int lo = 0, hi = n - 1;
steps = 0;
while (lo <= hi) {
++steps;
int mid = lo + (hi - lo) / 2;
if (arr[mid] == key) return mid;
if (arr[mid] < key) lo = mid + 1;
else hi = mid - 1;
}
return -1;
}
/* generic min/max/average via pointer out-params */
template <typename T>
void stats(const T arr[], int n, T &mn, T &mx, double &avg) {
mn = mx = arr[0];
double sum = 0;
for (int i = 0; i < n; i++) {
if (arr[i] < mn) mn = arr[i];
if (arr[i] > mx) mx = arr[i];
sum += arr[i];
}
avg = sum / n;
}
template <typename T>
void print(const char *tag, const T arr[], int n) {
std::cout << " " << tag;
for (int i = 0; i < n; i++) std::cout << arr[i] << " ";
std::cout << "\n";
}
int main() {
/* works on ints */
int a[] = {45, 12, 78, 3, 56, 91, 23};
int n = 7;
print("before : ", a, n);
bubbleSort(a, n);
print("sorted : ", a, n);
int steps;
int idx = binarySearch(a, n, 56, steps);
std::cout << " find 56 -> index " << idx
<< " in " << steps << " steps\n";
idx = binarySearch(a, n, 99, steps);
std::cout << " find 99 -> " << idx
<< " (absent) in " << steps << " steps\n";
int mn, mx; double avg;
stats(a, n, mn, mx, avg);
std::cout << " min=" << mn << " max=" << mx
<< " avg=" << avg << "\n";
/* the SAME functions on strings β zero new code */
std::string s[] = {"Sita", "Ram", "Hari", "Gita", "Bikash"};
print("strings: ", s, 5);
bubbleSort(s, 5);
print("sorted : ", s, 5);
std::string mns, mxs; double dummy = 0;
/* stats needs sum on T β strings support += so it
"works", but the average is meaningless. See below. */
/* and on doubles */
double d[] = {3.7, 1.2, 9.9, 5.5};
bubbleSort(d, 4);
print("doubles: ", d, 4);
return 0;
}
Output:
before : 45 12 78 3 56 91 23
sorted : 3 12 23 45 56 78 91
find 56 -> index 4 in 3 steps
find 99 -> -1 (absent) in 3 steps
min=3 max=91 avg=44
strings: Sita Ram Hari Gita Bikash
sorted : Bikash Gita Hari Ram Sita
doubles: 1.2 3.7 5.5 9.9
#include <iostream>
#include <string>
#include <typeinfo>
template <typename T>
void byValue(T x) {
std::cout << " byValue T=" << typeid(T).name()
<< " size=" << sizeof(T) << "\n";
}
template <typename T>
void byRef(T &x) {
std::cout << " byRef T=" << typeid(T).name()
<< " size=" << sizeof(T) << "\n";
}
template <typename T>
void byConstRef(const T &x) {
std::cout << " byConstRef T=" << typeid(T).name()
<< " size=" << sizeof(T) << "\n";
}
/* a template CANNOT deduce its RETURN type from context */
template <typename T>
T makeDefault() { return T{}; }
int main() {
int arr[10] = {};
int i = 42;
const int ci = 7;
/* by value: arrays DECAY to pointers, const is DROPPED */
byValue(arr); /* T = int* β size 8, not 40! */
byValue(ci); /* T = int β const stripped */
/* by reference: NO decay, const PRESERVED */
byRef(arr); /* T = int[10] β size 40 */
byConstRef(arr); /* T = int[10] β size 40 */
byRef(i); /* T = int */
/* return type cannot be deduced from the assignment */
/* int v = makeDefault(); error: couldn't deduce T */
int v = makeDefault<int>();
std::string s = makeDefault<std::string>();
std::cout << " makeDefault<int>() = " << v
<< ", string is " << (s.empty() ? "empty" : s) << "\n";
return 0;
}
Output:
byValue T=Pi size=8
byValue T=i size=4
byRef T=A10_i size=40
byConstRef T=A10_i size=40
byRef T=i size=4
makeDefault<int>() = 0, string is empty
template <std::integral T> instead of hoping the caller passes something sensible, with error messages that point at the call rather than 200 lines into the standard library. Second, variadic templates (template <typename... Args>) let one function take any number of arguments of any types; that is how std::make_unique, emplace_back and std::format are all implemented. Search "C++20 concepts requires clause" and "variadic template parameter pack".maximum, mySwap and a generic bubbleSort are the three standard questions. Explain instantiation: the compiler generates a separate function per type set, so unused templates cost nothing and heavy use causes code bloat. Know that typename and class are interchangeable in the parameter list. State clearly that deduction cannot mix types on one parameter (maximum(3, 7.5) fails) and that return types are never deduced from context. Contrast templates with C macros on type safety.Create a free account to tick topics off, take notes as you read, watch the video lessons and get a day-by-day study plan built around your exam date.
Loadingβ¦