Programming Language & Its Applications β Generic Programming and Exception Handling, NEC licence examination syllabus (Nepal Engineering Council).
Templates and ordinary functions competing for the same call β and the precise rules that decide the winner.
std::swap is a template, but std::vector supplies its own overload that swaps three internal pointers instead of copying every element β turning an O(n) operation into O(1). std::max has a general template plus an initializer_list overload. Every time you write a fast path for one specific type while keeping a generic fallback, you are using this mechanism. Search "std::swap specialization vs overload"; the answer explains why library authors prefer overloading to specialisation, which is a genuinely subtle distinction that trips up experienced programmers.#include <iostream>
#include <string>
/* 1. the general template */
template <typename T>
void show(T v) {
std::cout << " [template] " << v << "\n";
}
/* 2. a MORE SPECIALISED template β takes a pointer */
template <typename T>
void show(T *p) {
std::cout << " [template T*] " << *p << "\n";
}
/* 3. an ordinary non-template function */
void show(int v) {
std::cout << " [non-template] " << v << "\n";
}
/* 4. an explicit specialisation for double */
template <>
void show<double>(double v) {
std::cout << " [specialised] " << v << " (double)\n";
}
int main() {
int i = 42;
double d = 3.14;
char c = 'x';
std::string s = "hello";
show(i); /* non-template: EXACT match */
show(d); /* specialised template for double */
show(c); /* template T=char (non-template
would need char->int conversion) */
show(s); /* template T=std::string */
show(&i); /* the T* overload is MORE
specialised than T */
/* force the template even though a non-template
exact match exists */
show<int>(i); /* explicit: template T=int */
/* a conversion the template will NOT do */
show(7L); /* long: template T=long wins over
long->int conversion */
return 0;
}
Output:
[non-template] 42
[specialised] 3.14 (double)
[template] x
[template] hello
[template T*] 42
[template] 42
[template] 7
char and long cases together give the cleanest statement of the rule: a non-template wins only when it matches as well as the template. The moment it needs any conversion β a promotion for char, a narrowing for long β the template's exact match takes it. So adding void show(int) to a codebase changes behaviour for int arguments only, never for anything that merely converts to int.
#include <iostream>
#include <cstring>
/* ---- the generic version ---- */
template <typename T>
bool isEqual(T a, T b) {
std::cout << " (generic) ";
return a == b;
}
/* ---- SPECIALISATION for const char*: compare CONTENT,
not pointer addresses ---- */
template <>
bool isEqual<const char*>(const char *a, const char *b) {
std::cout << " (specialised for const char*) ";
return std::strcmp(a, b) == 0;
}
/* ---- an OVERLOAD taking two different types ---- */
template <typename T, typename U>
bool isEqual(T a, U b) {
std::cout << " (two-type overload) ";
return a == b;
}
int main() {
std::cout << std::boolalpha;
std::cout << " isEqual(5, 5) = ";
std::cout << isEqual(5, 5) << "\n";
std::cout << " isEqual(2.5, 2.5) = ";
std::cout << isEqual(2.5, 2.5) << "\n";
/* WITHOUT the specialisation this compares ADDRESSES
and would print false for equal text */
const char *s1 = "hello";
char buf[10]; std::strcpy(buf, "hello");
const char *s2 = buf;
std::cout << " isEqual(\"hello\", buf) = ";
std::cout << isEqual(s1, s2) << "\n";
std::cout << " isEqual(5, 5.0) = ";
std::cout << isEqual(5, 5.0) << "\n";
return 0;
}
Output:
isEqual(5, 5) = (generic) true
isEqual(2.5, 2.5) = (generic) true
isEqual("hello", buf) = (specialised for const char*) true
isEqual(5, 5.0) = (two-type overload) true
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
/* level 1: the catch-all template */
template <typename T>
void describe(const T &v) {
std::cout << " generic : " << v << "\n";
}
/* level 2: overload for pointers β dereference and mark */
template <typename T>
void describe(T *p) {
if (!p) { std::cout << " pointer : nullptr\n"; return; }
std::cout << " pointer to : " << *p << "\n";
}
/* level 3: overload for a vector β iterate */
template <typename T>
void describe(const std::vector<T> &v) {
std::cout << " vector[" << v.size() << "] : ";
for (const T &x : v) std::cout << x << " ";
std::cout << "\n";
}
/* level 4: non-template exact matches for the types that
need special treatment */
void describe(bool b) {
std::cout << " bool : " << (b ? "true" : "false") << "\n";
}
void describe(char c) {
std::cout << " char : '" << c << "' (ASCII "
<< int(c) << ")\n";
}
void describe(double d) {
std::cout << " double : " << std::fixed
<< std::setprecision(4) << d
<< std::defaultfloat << "\n";
}
int main() {
int i = 42;
double d = 3.14159265;
char c = 'A';
bool b = true;
std::string s = "Nepal";
std::vector<int> v{10, 20, 30};
int *p = &i;
int *np = nullptr;
describe(i);
describe(d);
describe(c);
describe(b);
describe(s);
describe(v);
describe(p);
describe(np);
return 0;
}
Output:
generic : 42
double : 3.1416
char : 'A' (ASCII 65)
bool : true
generic : Nepal
vector[3] : 10 20 30
pointer to : 42
pointer : nullptr
if constexpr, which lets one function branch on the type at compile time instead of needing separate overloads: if constexpr (std::is_pointer_v<T>) { ... } else { ... }, with the untaken branch never even compiled. C++20 concepts go further still, letting you order overloads by constraint. Before either existed, library authors used a technique called SFINAE (std::enable_if) which worked but produced famously unreadable code. Search "if constexpr vs SFINAE vs concepts" to see the same problem solved three times across twenty years β it is a good short history of modern C++.template <> void f<int>(int) with its empty angle brackets, and the key distinction: a specialisation supplies a body for an existing template and does not take part in overload resolution, whereas an overload does. Mention that function templates allow only full, never partial, specialisation.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β¦