Visual walkthrough — Template specialization — full and partial
5.2.15 · D2· Coding › C++ Programming › Template specialization — full and partial
Hum ek ek idea build karte hain. Neeche kuch bhi assume nahi kiya gaya ki tumne parent note se kuch yaad kiya — hum har word ko dobara earn karte hain.
Step 1 — Ek template ek stamp hai jo kai boxes banata hai
KYA. Sabse generic cheez se shuru karte hain: ek primary template.
template<class T>
struct Box { /* generic recipe */ };template<class T> ko zor se padho: "jo bhi type tum mujhe do, jise T kaha jaayega, main isi tarah ek Box banaaunga." struct ka matlab sirf "data aur functions ka ek chhota bundle" hai. T ek blank slot hai — ek placeholder jo kisi real type jaise int ya double ka intezaar kar raha hai.
KYUN. Compiler har type ke liye advance mein ek box ship nahi kar sakta — types infinite hain. Toh iski jagah wo ek stamp ship karta hai: ek machine jo, jab tum Box<int> likhte ho, ek fresh Box press karti hai jisme T slot mein int bhar jaata hai. Is pressing ko instantiation kehte hain.
PICTURE. Baayein taraf stamp; daayein taraf teen pressed boxes, har ek mein alag type daali gayi hai.

Step 2 — Har type ek point hai; ek template types ka ek REGION cover karta hai
KYA. Socho ki saare possible types ko ek bade sheet par dots ki tarah draw kar rahe ho — int, double, int*, char*, pair<int,char>, wagera. Ab ek boundary khiincho un types ke set ke around jo ek given stamp serve karne ko taiyaar hai. Us boundary ko hum stamp ka match region kehte hain.
KYUN. Poora selection problem visual ho jaata hai jab hum regions mein sochte hain. Primary template<class T> sab kuch serve karta hai — uska match region poori sheet hai. Ek specialization iske andar ek chhota region draw karegi. "Kaun si recipe jeeiti hai" ka matlab ho jaata hai "kaun sa region X point ke around sabse chhota hai."
PICTURE. Type-dots ki poori sheet. Ek dashed outer rectangle jisme likha hai "primary T — matches ALL types" har dot ko wrap karta hai.

Step 3 — Full specialization: ek region jisme sirf EK point ho
KYA. Ek full specialization saare parameters ko concrete types se pin karta hai, toh uska region ek single dot tak chhota ho jaata hai.
template<> // koi slot nahi bacha — zero free parameters
struct Box<int> { // yeh exact type: int
/* int ke liye custom recipe */
};Term by term:
template<>— angle brackets khaali hain kyunki tumne har slot fill kar diya; compiler ko deduce karne ke liye kuch nahi bacha.Box<int>— woh ek instantiation name karta hai jise tum replace kar rahe ho. Yeh the dot hai.
KYUN. Kabhi kabhi generic recipe exactly ek type ke liye galat, slow, ya impossible hoti hai (parent se std::vector<bool> bit-packing yaad karo). Full specialization tumhe us single point ko hijack karne deta hai bina kuch rename kiye — callers phir bhi Box<int> likhte hain.
PICTURE. Step 2 ki sheet, ab ek tiny circle ke saath jo single int dot ko lasso kar rahi hai, label hai "full spec Box<int> — 1 type". double aur int* dots bahar hain, phir bhi primary serve karta hai.

Step 4 — Partial specialization: ek region jo EK FAMILY jaisi shaped hai
KYA. Ek partial specialization sirf type ki shape ko pin karta hai, kuch slots free rakhta hai.
template<class T> // T abhi bhi ek free slot hai
struct Box<T*> { // lekin type "pointer to something" jaisi dikhni chahiye
/* kisi bhi pointer ke liye custom recipe */
};Term by term:
template<class T>— ek slot abhi bhi free hai; yahi ise full ki jagah partial banata hai.Box<T*>— pattern.*ka matlab hai "koi bhi type match karta hai jo pointer-to-T form mein ho."int*match karta haiT = intke saath;char*match karta haiT = charke saath;intnahi match karta (koi*nahi).
KYUN. Aksar tum ek poori family ke liye ek custom recipe chahte ho — "saare pointers," "saare pair<A,B>" — na ek single type na sab kuch. Kyunki function overload resolution already function families handle karta hai, C++ sirf class templates par partial specialization allow karta hai (parent mein mistake-callout: functions ko overloads milte hain).
PICTURE. Sheet phir se, ab ek medium oval ke saath jo har *-dot (int*, char*, double*) ko enclose karta hai, label hai "partial spec T* — the pointer family". Yeh primary rectangle ke andar baith ta hai lekin kisi single point se bada hai.

Step 5 — Selection rule, baahir se andar walk ke roop mein
KYA. Query type X ko sheet par ek star ke roop mein rakho. Compiler har us stamp ko collect karta hai jiska region star ko contain karta hai, phir sabse chhota aisa region rakhta hai.
KYUN. "Star ko contain karne wala sabse chhota region" exactly wahi plain-English rule hai "most specialized match wins." Full spec (single point) partial (family) ko beat karta hai, jo primary (sab kuch) ko beat karta hai — lekin sirf unme se jo actually star ko contain karte hain.
PICTURE. X = int* ke liye: star primary rectangle aur T* oval ke andar land karta hai, lekin Box<int> point-circle ke baahir. Do nested regions ise contain karte hain; inner T* oval jeeetta hai. Arrows dikhate hain ki compiler "shrinking inward" karta hai jab tak koi chhota region star contain na kare.

Step 6 — Do regions ki comparison: partial ordering
KYA. Jab tumhare paas kai partials hain, "chhota region" ko ek precise test chahiye, jise partial ordering kehte hain. Spec A, B se zyada specialized hai agar har type jo A match karta hai wo B bhi match karta hai, lekin ulta nahi.
KYUN. "Chhota" sheet par intuitive tha; compiler ko ek mechanical version chahiye. Partial ordering exactly hai "A ka region B ka region aur wo equal nahi hain" — set containment, lekin drawing ki jagah matching game se compute hota hai.
PICTURE. Do ovals. pair<int,B> (pehla slot int se fix, doosra free) pair<A,B> (dono free) ke andar baith ta hai. Har pair<int, something> bhi ek pair<A,B> hai, lekin har pair<A,B> ka pehla int nahi hota — toh inner wala zyada specialized hai.

Step 7 — Degenerate case: do regions jo CROSS karti hain (ambiguity)
KYA. Kya ho agar do partials overlap karein lekin na to ek doosre ke andar poori tarah ho? Tab us type ke liye jo overlap mein hai, koi sabse chhota region nahi hota — aur compiler guess karne se mana kar deta hai.
template<class A, class B> struct M {};
template<class A> struct M<A, int> {}; // region: "doosra slot int hai"
template<class B> struct M<int, B> {}; // region: "pehla slot int hai"
M<int, int> m; // ERROR: ambiguousTerm by term:
M<A,int>sab kuch cover karta hai jiska doosra parameterinthai.M<int,B>sab kuch cover karta hai jiska pehla parameterinthai.M<int,int>dono regions mein ek saath hota hai — crossing zone.
KYUN. Na to koi region doosre ka subset hai (dono mein aisi points hain jo doosre mein nahi hain: M<char,int> sirf pehle mein; M<int,char> sirf doosre mein). Toh partial ordering koi winner nahi deta. Random choice karne ki jagah, compiler ambiguity error emit karta hai — yeh ek feature hai, jo tumhe silent galat choices se bachata hai.
PICTURE. Do overlapping ovals jo Venn diagram banate hain. Lens-shaped overlap mein single dot M<int,int> hai, amber mein flag hua "AMBIGUOUS — no smallest region."

Ek-picture summary
Jo bhi upar hai wo ek hi idea hai: regions ko nest karo, star drop karo, sabse inner region rakho jo usse contain karti ho. Full spec = ek point, partial spec = ek shaped family, primary = poori sheet. Overlapping-but-not-nested regions jin mein star overlap mein hai = ambiguity.

Recall Feynman: poori walkthrough apne plain words mein retell karo
Ek giant sheet of paper imagine karo jisme existence mein har type ke liye ek dot hai. Generic template ek aalsi fence hai jo saare dots ke around khiinchi gayi hai — wo kisi ko bhi serve karega. Ek full specialization ek tiny lasso hai exactly ek dot ke around: "int ke liye, meri recipe use karo." Ek partial specialization ek medium loop hai ek family of dots ke around jo ek shape share karte hain — "saare pointers," "saare pairs." Ab koi ek type maangta hai: us type ke dot par ek star drop karo. Compiler har us fence, loop, aur lasso ko dekhta hai jo star ko surround karta hai aur sabse tight wala rakhta hai — kyunki sabse tight region ka matlab hai "tumhara clearly yahi special case mein tha." Ek-dot lasso ek family loop ko beat karta hai jo everything-fence ko beat karta hai. Sirf ek hi tarika hai jab yeh toot ta hai — agar do loops cross karein aur star crossing region mein ho: ab koi single tightest loop nahi, toh compiler haath utha kar kehta hai "ambiguous" instead of guess karne ke. Ise fix karo ek aur bhi choti lasso draw karke — ek full spec — bilkul disputed dot par.
Recall
Full specialization ki region-shape kaun si hoti hai? ::: Ek single point — saare parameters pinned. Partial specialization ki region-shape kaun si hoti hai? ::: Ek shaped family — kuch parameters free, type ka structure constrained. Matching regions mein winner kaun? ::: Sabse chhota region jo abhi bhi query type contain karta ho. Do partials overlap karte hain lekin na ek doosre ke andar, aur X overlap mein hai — result? ::: Ambiguity error; koi most-specialized choice exist nahi karti. "A more specialized than B" ka formal test? ::: match(A) ⊆ match(B) aur match(A) ≠ match(B).
Related vault topics: Templates — function and class basics · Type Traits and std::is_pointer · SFINAE and enable_if · Overload Resolution vs Specialization · std::vector<bool> special case · Tag Dispatch and Policy-based Design · constexpr if (C++17) — alternative to specialization