Foundations — Concepts (C++20) — constraining templates
5.2.18 · D1· Coding › C++ Programming › Concepts (C++20) — constraining templates
Yeh page kuch bhi assume nahi karta. Parent page par use kiya gaya har symbol, keyword aur squiggle yahan unpack kiya gaya hai, ek aisi order mein jahan har item sirf usse pehle waalon par tikaa hai. Agar parent page ki koi line confusing lagi, woh symbol neeche dhundho.
0. Woh picture jis par hum baar baar aate hain
Template ko ek cookie-cutter ki tarah socho, aur ek type (ek label jaise "pura number" ya "text" — Section 1 mein properly define kiya gaya) ko aate ke ek tukde ki tarah. Cutter ek asli function ya class stamp karta hai jab tum use ek specific aata dete ho. Ek concept cutter par chipka ek sign hai: "sirf chocolate ya sugar ka aata — patther nahi." Sign door par check hota hai, cookie baad mein banaane ke baad nahi.
Figure s01 (neeche): teal cookie-cutter ek dashed blank slot carry karta hai jis par T likha hai; upar chipka orange sign padhta hai "sirf numeric dough"; daayein taraf, ek int plug fit hota hai (green true) jabki ek string block ko wapas kar diya jaata hai (orange false). Yeh har agli section ke liye mental image hai.

1. type — ek value kya hai
Picture: ek type ek socket ki shape hai. Ek round plug (int) ek round socket mein fit hota hai; woh square socket mein nahi jaayega (jahan whole number chahiye wahan decimal). + jaisi operations "prongs" hain — ya toh socket mein hain ya nahi.
Yeh topic ko kyun chahiye: concepts types ke baare mein sawaal hain. Isse pehle ki tum pooch sako "kya yeh type + support karti hai?", tumhe yeh maanna padega ki ek type ek cheez hai jo allowed operations ka ek fixed set carry karti hai. Dekho Templates — function & class templates jahan types plug in hoti hain.
2. template<typename T> — cookie-cutter aur uska blank
template<typename T> // "T ek type-shaped blank hai"
T add(T a, T b) { return a + b; } // body us blank ko use karti haiPicture: figure s01 ki cutter shape, jisme empty slot par T likha hai. Baad mein tum us slot mein ek real type fill karte ho (int, double, ...) — same cutter, alag alag cookies. Slot fill karne ka exact notation <...> hai, jo Section 5 mein unpack hota hai.
Yeh topic ko kyun chahiye: ek concept us blank se attached hota hai taaki restrict kar sake ki use kya fill kar sakta hai. Blank nahi toh constraint karne ke liye kuch nahi. Yeh ek prerequisite hai jis par poora parent note tikaa hai.
3. constexpr aur "compile time" — check kab hoti hai
Picture: do ghariyan. Clock A tab tik karti hai jab chef (compiler) recipe padh raha hota hai. Clock B tab tik karti hai jab diner (running program) kha raha hota hai. Ek constexpr value — aur har concept check — poori tarah Clock A par hoti hai — jab Clock B shuru hoti hai, tab tak saari constraints pass ho chuki hoti hain.

Yeh topic ko kyun chahiye: parent note kehta hai ek concept "ek constexpr bool template hai ... kabhi runtime par nahi chalta." Woh sentence meaningless hai jab tak tum yeh do ghariyan nahi dekhte. Dekho constexpr — compile-time evaluation.
4. bool, predicate, aur true/false
Picture: ek light switch — upar (true) ya neeche (false). Ek concept ek aisa switch hai jiski position is par depend karti hai ki tum use kaunsi type feed karte ho: ek whole-number type feed karo toh jal jaata hai, text feed karo toh neeche rehta hai.
Yeh topic ko kyun chahiye: ek concept ek predicate hi hota hai. Numeric<T> (jahan <...> Section 5 hai) padhta hai "kya T numeric hai?" aur true ya false se jal jaata hai. Parent note mein baaki sab us ek light switch ko compute karne ki machinery hai.
5. <...> — angle brackets (template ko uski type dena)
Picture: cutter par blank slot (figure s01) physically fill ho raha hai. <int> slot mein int drop karta hai.
Yeh topic ko kyun chahiye: parent mein har concept use — Numeric<T>, std::integral<T>, std::same_as<T> — angle-bracket substitution hai. <...> ko "blank fill karo" ki tarah pehchaanna zaroori hai. Ab jo blank (Section 2) aur filling notation dono define ho gayi hain, add<int> aur Numeric<int> poori tarah samajh aate hain.
6. std:: — standard library ka name tag
Picture: ek labelled drawer. std drawer mein sab kuch standard-issue aur pehle se tested hai. std::integral, std::floating_point, std::same_as, std::convertible_to, std::begin, std::cout, std::string, std::vector sab wahan rehte hain.
Yeh topic ko kyun chahiye: Numeric jaisi concepts ready-made std:: concepts se bani hain. Ab jo std:: aur <...> dono define ho gayi hain, pehle loosely use ki gayi "text" (std::string) aur "ints ki list" (std::vector<int>) ki phrases poori tarah spell out ho gayi hain. Dekho type_traits — std::integral, std::floating_point.
7. ||, && — true/false jawaab combine karna
Picture: do switches ek saath wire kiye hue. || ke liye, koi bhi ek switch akela bulb jala deta hai. && ke liye, tumhe dono switches upar chahiye.
template<typename T>
concept Numeric = std::integral<T> || std::floating_point<T>;
// true agar T whole number hai YA T decimal number haiYeh topic ko kyun chahiye: parent ka pehla concept, Numeric, do simpler predicates ka or hai. Ek requires-expression ki requirements ki list implicitly ek and hai — har line compile honi chahiye.
8. concept Name = ...; — ek predicate ko naam dena
Picture: cutter par chipke sign par words likhna (figure s01). Pehle, rule kahin nahi tha; ab uske paas ek reusable label hai.
Yeh topic ko kyun chahiye: naam dene se ek darauni boolean formula ek readable word ban jaati hai jise tum reuse kar sakte ho aur error messages mein daal sakte ho ("std::string ne Numeric satisfy nahi kiya").
9. requires (do hain) — confusing twin keywords
Parent note stress karta hai ki do alag requires hain. Yahan woh picture hai jo inhe alag karti hai.

10. Requirement mein ->, plus *, std::begin, decltype
Parent ka decltype(*std::begin(r)) padhne se pehle, chaar chhote symbols ko naam chahiye.
Picture: arrow -> ek customs checkpoint hai expression compile hone ke baad: result ko sahi "type passport" dikhani padti hai. * ek ungli hai jo cursor ko std::begin se wahan tak follow karti hai jahan woh actual element point kar raha hai. Dekho auto and decltype.
Yeh topic ko kyun chahiye: compound requirement ({e} -> C) chaar requirement kinds mein se ek hai, aur parent ka Printable concept decltype(*std::begin(r)) use karta hai "element type" ko naam dene ke liye taaki test kar sake ki kya elements streamable hain.
11. Overloading & subsumption — zyada rules kyun jeette hain
Picture: do doormen. Door A: "sirf wholes." Door B: "sirf positive wholes." Ek +5 dono satisfy karta hai, lekin B stricter hai, toh bheed B se guzaari jaati hai. Ek unsatisfied door error nahi hai — woh guest simply us door ka use nahi kar sakta.
Yeh topic ko kyun chahiye: yeh parent ki "killer feature" hai. Dekho Overload Resolution & Subsumption. Dhyan do iska purana, clumsy tarika — SFINAE and std::enable_if — jo concepts replace karte hain.
Prerequisite map
Related tooling jo yeh feed karta hai: Ranges library (C++20) (jiske Printable-style range concepts parent ke worked example mein aate hain) aur poora parent note Hinglish version.
Equipment checklist
Ek type ko best kaise describe karein
template<typename T> ek phrase mein
T hai, baad mein fill hoga.template<...> ke andar typename vs class
Compile time vs run time
constexpr keyword kya guarantee deta hai
Ek bool hai
true ya false ho.Ek predicate hai
Numeric<int> ka matlab
Numeric predicate ko blank T = int set karke run karo, true ya false milega.std:: prefix ka matlab
std::vector<int> padhta hai
int hain (bracket = element blank fill karo).A || B kab true hota hai
A, B mein se kam se kam ek true ho.Ek concept definition kya karta hai
requires-clause vs requires-expression
Kya braces { a + b } a+b compute karte hain?
a + b compile hoga ya nahi, uski value nahi.Ek simple requirement vs compound requirement
; par khatam, koi arrow nahi, sirf "compile hoga?" poochha; compound = { e } -> C, result type bhi pin down karta hai.Ek type requirement kaisi dikhti hai
typename T::value_type; — assert karta hai ki ek nested type exist karti hai.Ek nested requirement kaisi dikhti hai
requires Numeric<T>; — factory ke andar ek aur poori constraint bolt karta hai.*std::begin(r) mein dereference * deta hai
r ka pehla element.std::begin(r) return karta hai
r ke pehle element ko point karta hai.{ expr } -> C check karta hai
expr compile hota hai AND uske result ka type concept C satisfy karta hai.decltype(e) ka matlab
e ki hogi.