Visual walkthrough — Templates — function templates, class templates
5.2.14 · D2· Coding › C++ Programming › Templates — function templates, class templates
Yeh main Templates note ka ek companion hai. Yeh ideas par lean karta hai Compile-time vs Runtime, Function Overloading, aur Type Deduction (auto) se. Neeche har ek word zero se bana hai — tumhe bas itna jaanna chahiye ki "ek function inputs leta hai aur ek output return karta hai."
Step 1 — EK concrete function se shuru karo
KYA. Hum sabse simple possible function likhte hain jo do puri numbers mein se badi wali return karta hai.
int maximum(int a, int b) { return (a > b) ? a : b; }KYUN yahan se shuru karein. Tum kisi cheez ko generalize nahi kar sakte jab tak use pehle concrete na bana lo. Body dekho: (a > b) ? a : b ka matlab hai "agar a, b se bada hai, toh a wapas do, warna b wapas do." Woh chota sa ?: ternary operator kehlata hai — use ek line wale "if/else jo ek value produce karta hai" ki tarah padho. Dekho body ko actually kya chahiye: use do cheezon ko > se compare karna chahiye, aur use ek wapas copy karni chahiye. Yeh kabhi kuch bhi use nahi karta jo int ke liye special ho.
PICTURE. Function ek box hai. Do int values left se jaati hain; ek int right se nikalti hai.
int word teen baar aata hai — red colour mein — aur woh teeno reds ek promise hain jo kehte hain "yahan sirf puri numbers allowed hain."

Step 2 — Notice karo ki type hi akela cheez hai jo badlti hai
KYA. Maan lo ab tumhe do doubles (decimals) ka maximum chahiye. Tum copy-paste karo aur har int ko double se badal do:
double maximum(double a, double b) { return (a > b) ? a : b; }KYUN yeh dikhayein. Dono functions ko side by side rakho. Bodies byte-for-byte identical hain. Sirf fark hai teen type labels mein. Yahi templates ka pura motivation hai: duplicated part (logic) ek baar likhna chahiye; varying part (type) ek knob ban jaana chahiye jise tum ghuma sako.
PICTURE. Do boxes stacked. Unke andar — (a>b)?a:b gear — same green gear hai.
Sirf input/output labels alag hain (int red upar, double orange neeche). Green gear woh hai jise hum rakhna chahte hain; coloured labels woh hain jise hum swappable banana chahte hain.

Step 3 — Type ko ek placeholder naam T se replace karo
KYA. Ek fixed type likhne ki jagah, hum ek placeholder invent karte hain aur use T kehte hain. Hum compiler ko batate hain "T ek type hai jo main baad mein fill karunga" ek header line ke saath, aur phir T use karte hain jahan bhi type gaya tha.
template<typename T> // "T kisi type ke liye stand karta hai — choose hona baki hai"
T maximum(T a, T b) { // wahi teen labels, ab sab T
return (a > b) ? a : b; // green gear, untouched
}KYUN yeh exact syntax. template<typename T> compiler ka word hai "jo aage hai woh ek blueprint hai, aur T iska blank hai." typename word yahan sirf matlab hai "T ek type naam karta hai." (Parent note batata hai typename aur class yahan interchangeable hain — same meaning.) Blueprint abhi code nahi hai — yeh ek shape hai jisme ek hole hai jis par T likha hai.
PICTURE. Step 1 jaisa wahi box, lekin teen red int labels ko teen blue T labels se replace kar diya gaya hai, aur ek nayi banner template<typename T> upar baith gayi hai ek nameplate ki tarah. Poori cheez ke around ek dashed grey outline signal karta hai "yeh ek blueprint hai, real function nahi — abhi koi machine code exist nahi karta."

Step 4 — Compiler hole bharta hai: instantiation
KYA. Tum blueprint ko real arguments ke saath call karte ho:
maximum(3, 7); // dono arguments int hainCompiler arguments 3 aur 7 dekhta hai, paata hai woh int hain, aur T hole ko int se fill karta hai. Sirf tab real code appear hota hai.
KYUN compiler yeh akele kar sakta hai. Yeh type deduction hai (same machinery jo auto ke peeche hai): compiler arguments ke types padhta hai aur T solve karta hai. Yahan 3 → int aur 7 → int, toh T = int. Phir woh har T ki jagah int substitute karta hai aur generate karta hai:
int maximum(int a, int b) { return (a > b) ? a : b; }— jo bilkul wahi function hai jo humne Step 1 mein haath se likhi thi. Humne use free mein paya.
PICTURE. Blue-T blueprint left par. Ek arrow labelled T = int right mein flow karta hai ek
solid (ab dashed nahi) red box mein — ek real, callable int function. Arrow instantiation ka kaam hai; solid box stamped-out cookie hai.

Step 5 — Ek blueprint, bahut saari cookies (aur unused types ke liye koi nahi)
KYA. Ab use aur types ke saath call karo:
maximum(3, 7); // T = int -> int version stamp karta hai
maximum(2.5, 1.1); // T = double -> double version stamp karta hai
maximum<char>('a','z'); // T = char, explicitly force kiya gayaKYUN teesra alag lagta hai. maximum<char>(...) type ko haath se angle brackets ke andar dalta hai compiler ko guess karne dene ki jagah. Tum yeh tab karte ho jab tum ek type force karna chahte ho. Baaki sab automatically deduce ho jaata hai.
The crucial edge fact: ek type jise tum kabhi call nahi karte woh zero code produce karta hai. Agar tumhara program kabhi string par maximum nahi karta, toh koi string maximum final program mein exist nahi karta. Blueprint hai "sirf jo use karo uske liye pay karo."
PICTURE. Center mein ek blue blueprint. Teen solid boxes usse fan out karte hain — red int,
orange double, green char — har ek apne T = ... se labelled. Ek greyed-out, crossed-through
ghost box labelled string (never called) side mein baith hai yeh dikhane ke liye ki woh nahi banta.

Recall
Agar ek program maximum sirf int aur double par call karta hai, toh kitne real functions generate hote hain? ::: Exactly do — ek int ke liye, ek double ke liye. Unused types kuch generate nahi karte.
Step 6 — Degenerate case: conflicting deductions
KYA. Ek call mein types mix karne ki koshish karo:
maximum(3, 2.5); // 3 int hai, 2.5 double haiYeh compile nahi hota.
KYUN fail hota hai. Deduction ko ek akela T produce karna hoga. Pehla argument kehta hai "T ko int hona chahiye"; doosra kehta hai "T ko double hona chahiye." Compiler dono nahi maan sakta, toh woh refuse karta hai — woh silently tumhare liye ek nahi chunega. Yeh ek feature hai: yeh tumhe ek hidden, possibly wrong, conversion se rokta hai.
Do fixes:
maximum<double>(3, 2.5); // T = double force karo; int 3 convert hota hai 3.0 meinya dono parameters ko independent types banao:
template<typename T1, typename T2>
auto maximum(T1 a, T2 b) { return (a > b) ? a : b; } // C++14 return type deduce karta haiPICTURE. Blueprint apne single T hole ke saath. Do arrows usi ek hole mein point karte hain: ek red wala int carry karta hai, ek orange wala double carry karta hai. Woh hole par collide karte hain aur ek red ✗ conflict flag karta hai — "ek hole, do incompatible demands."

Step 7 — Classes ke liye same machine: Box<T> blueprint
KYA. Bilkul same idea poori classes par apply hoti hai. Ek class data + functions bundle karta hai. Hum ek aisa banate hain jiska stored type ek hole hai:
template<typename T>
class Box {
T value; // stored cheez hole type T ki hai
public:
Box(T v) : value(v) {} // ek T se Box banao
T get() const { return value; }
};KYUN tumhe Box<int> likhna hoga, sirf Box nahi. Ek function template T deduce karne ke liye apne arguments dekh sakta hai. Ek class template (C++17 se pehle) ke paas kuch dekhne ko nahi hota jab tum pehli baar type naam lete ho, toh tum hole khud fill karte ho:
Box<int> bi(42); // ek class Box<int> instantiate karta hai
Box<string> bs("hi"); // ek ALAG class Box<string> instantiate karta haiBox<int> aur Box<string> alag types hain — utne hi unrelated jitne int aur string. Woh koi runtime code share nahi karte. Exactly aise hi vector<T> kaam karta hai.
PICTURE. Ek blue Box<T> blueprint ek T-shaped slot pakde hue. Usse do solid class boxes stamp kiye gaye: ek red Box<int> jisme 42 hai, aur ek green Box<string> jisme "hi" hai. Unke beech ek wall labelled "unrelated types — no shared code."

Ek-picture summary
KYA poore page ne kaha, ek frame mein. Concrete function → notice karo ki sirf type vary karta hai → ek T hole punch karo ek blueprint banane ke liye → compiler T deduce karta hai ya use bataya jaata hai → woh used har distinct type ke liye ek real cookie stamp karta hai, aur unused types ke liye kuch nahi; ek hole mein types mix karna woh ek degenerate case hai jo deduction tod deta hai.

Recall Feynman: poori walkthrough apne words mein retell karo
Maine ek aisi machine se shuru kiya jo sirf puri numbers chaba sakti hai. Maine notice kiya ki agar main chahta ki woh decimals chabe, toh main poori machine copy karta aur sirf "puri numbers" wale signs ko "decimals" kehne ke liye repaint karta — gear kabhi nahi badla. Toh maine signs bilkul utaar diye aur ek blank sign laga diya jo kehta hai "T — koi type, TBD," aur maine front par template<typename T> ka nameplate laga diya. Woh blank machine abhi real nahi hai; yeh ek machine ki drawing hai. Phir, jis moment main actually use do puri numbers deta hoon, factory (compiler) numbers padhti hai, sab blanks par int likhti hai, aur ek real puri-number machine turant weld kar deti hai. Kahin aur decimals do aur woh ek doosri, alag decimal machine weld karti hai. Agar main kabhi use text nahi deta, toh koi text machine kabhi nahi banti — main sirf wahi pay karta hoon jo use karta hoon. Ek cheez jo factory ko jam karti hai woh hai usi blank ko ek haath mein puri number aur doosre haath mein decimal dena: blank sirf ek type ban sakta hai, toh factory ruk jaati hai aur mujhse decide karne kehti hai. Classes same tarah kaam karti hain, sirf mujhe factory ko type pehle se batana hota hai Box<int> likhkar, kyunki ek class ke paas koi arguments nahi hote peek karne ke liye.