Function Templates & Generic Programming
ফাংশন টেমপ্লেট
1. Write Once, Use With Many Types
#include <iostream>
#include <string>
template<typename T>
T max(T a, T b) {
return a > b ? a : b;
}
int main() {
std::cout << max(3, 5) << "\n"; // int
std::cout << max(2.5, 3.5) << "\n"; // double
std::cout << max(std::string{"abc"}, std::string{"abd"}) << "\n";
}
2. Multiple Type Parameters
template<typename A, typename B>
auto add(A a, B b) {
return a + b; // return type deduced
}
// add(1, 2.5) -> double
// add(std::string{"hi"}, " there") -> std::string
3. Type Deduction Rules
- By default, T is deduced as the value type (no
const, no reference). T&in the parameter preservesconst.const T&works with everything (lvalue or rvalue).- Arrays decay to pointers unless taken by reference.
4. Explicit Type Specification
If deduction fails or you want to force a type:
auto r = max<double>(3, 5); // force T = double
5. Template Definitions Live in Headers
The compiler must see the full template body to instantiate it. So template implementations go in the header file, not a .cpp.
6. Cost of Templates
- Compile time: Each instantiation generates real code → bigger binaries, slower compile.
- Runtime: Zero. The generated code is identical to hand-written code for that type.
- Error messages: Historically cryptic. C++20 concepts fix this.
7. Practice Problems
- Write a generic
swapfunction.✨ Show Answer
template<typename T> void swap(T& a, T& b) { T t = std::move(a); a = std::move(b); b = std::move(t); } - Write a generic min/max.
✨ Show Answer
template<typename T> T min(T a, T b) { return a < b ? a : b; } template<typename T> T max(T a, T b) { return a > b ? a : b; } - Why is
typenameused intemplate<typename T>?✨ Show Answer
Both
typenameandclasswork — historical alternatives. They're equivalent. Modern style usestypename. - What's a non-type template parameter?
✨ Show Answer
template<int N> struct Array { int data[N]; }; Array<100> a; // N=100 at compile time - Generic print function.
✨ Show Answer
template<typename T> void print(const T& x) { std::cout << x << "\n"; } - Force type explicitly:
max<long>(1, 2). Why might this matter?✨ Show Answer
To prevent narrowing or pick a specific overload. E.g. avoid int overflow in intermediate computations.
- A template that prints type size.
✨ Show Answer
template<typename T> void printSize() { std::cout << sizeof(T) << "\n"; } // printSize<double>(); // 8 - Why must templates be in headers?
✨ Show Answer
The compiler instantiates only when it sees both the template definition and the use. If the body is in a separate .cpp, the linker can't find the instantiation.
- A function template with a default type parameter.
✨ Show Answer
template<typename T = int> T zero() { return T{}; } // zero(); // returns int 0 // zero<double>(); // returns 0.0 - Generic
sumover a vector.✨ Show Answer
template<typename T> T sum(const std::vector<T>& v) { T s{}; for (const auto& x : v) s += x; return s; } - Why are templates "zero-cost abstraction"?
✨ Show Answer
Because the compiler generates type-specific code at compile time. There's no runtime overhead — equivalent to hand-writing
maxInt,maxDoubleseparately. - Define a fold-like template that applies a binary op.
✨ Show Answer
template<typename Op, typename T> T reduce(const std::vector<T>& v, T init, Op op) { for (const auto& x : v) init = op(init, x); return init; } - Print all elements of a container generically.
✨ Show Answer
template<typename Container> void printAll(const Container& c) { for (const auto& x : c) std::cout << x << " "; } - What does
autoin a function parameter mean (C++20)?✨ Show Answer
An abbreviated function template.
void f(auto x)is equivalent totemplate<typename T> void f(T x). - Why might template error messages be cryptic?
✨ Show Answer
The compiler instantiates and then reports errors deep inside template machinery. C++20 concepts fix this by stating constraints up front and giving clean errors.
- Use a concept to constrain T to be integral (C++20).
✨ Show Answer
template<std::integral T> T square(T x) { return x * x; } - Show that
max(1, 2.5)fails to deduce.✨ Show Answer
Both args must agree on T.
1is int,2.5is double — ambiguous. Either cast or use two type params. - Specialize
maxforconst char*.✨ Show Answer
template<> const char* max(const char* a, const char* b) { return std::strcmp(a, b) > 0 ? a : b; }Without this,
max("a","b")compares pointers, not contents.
Summary
Function templates are compile-time code generation. They are zero-cost — the generated code is identical to hand-written. Templates live in headers. C++20 concepts make constraint checking and error messages much cleaner.