Visual walkthrough — std - function and std - bind
5.2.23 · D2· Coding › C++ Programming › std - function and std - bind
Is page mein parent parent topic se zyada gehraai hai. Agar koi word naya lage, toh yahan use karne se pehle define kiya gaya hai.
Step 1 — "Callable" kya hota hai? (raw ingredients)
KYA. Ek callable woh cheez hai jiske baad tum parentheses laga sako aur arguments pass kar sako. C++ mein inki chaar species hain, aur compiler ke liye yeh genuinely alag-alag jaanwar hain.
YE YAHAN SE KYU shuru karein. Tum ek aisi box ko samajh nahi sakte jo "koi bhi callable hold kare" jab tak tumne woh callables nahi dekhe jinhe usse hold karna hai — aur, sabse zaroori baat, yeh nahi dekha ki unke alag types hain. Wahi farq hi std::function ke existence ki wajah hai.
TASVEER. Chaar shapes, chaar colours, chaar type names. Dhyan do: do lambdas jo same kaam karti hain unke bhi alag unnamed types hote hain.

Jo letters hum baar baar use karte rahenge:
- ::: return type (yahan
int). - ::: parameter types ki list (yahan
int, int).
Step 2 — Obstacle: alag types ek variable share nahi kar sakte
KYA. Hum naively try karte hain ki sabhon ko ek variable mein store karein — aur fail ho jaate hain.
KYU. C++ mein ek variable ka ek fixed type hota hai. add ek function pointer hai; ek lambda koi hidden type __lambda_7 hai; Mul ek struct hai. Koi bhi aisa ordinary type nahi hai jo sab mein fit ho, toh naive auto x = add; x = someLambda; ek compile error hai.
TASVEER. Teen coloured pegs (round, square, triangular) ek round hole mein jaane ki koshish kar rahe hain. Do wapas bounce ho jaate hain. Red ✗ type mismatch ko mark karta hai.

Toh humein ek aisi hole chahiye jiske shape pe saare charon kuch share karte hon. Woh share kya karte hain?
Step 3 — Shared promise: call signature
KYA. Har callable ko sirf how you use it tak strip karo: do ints do, ek int wapas lo. Woh shape — likha hua — signature hai.
KYU yeh, type nahi. Concrete types alag hain, lekin usage shape identical hai: f(2,3) -> int. Agar hum apna box type ki jagah shape ke around banayein, toh charon fit ho jaate hain. Yahi key idea hai jo sab kuch unlock karta hai.
TASVEER. Charon callables ek stencil se funnel hote hain jis par int(int,int) likha hai. Stencil ke baad sirf yeh bachta hai: "2 ints in, 1 int out".

Step 4 — Box banana: type erasure
KYA. std::function<R(Args...)> ek class hai jiska only kaam yeh hai: us signature se match karna wala koi bhi callable hold karo, aur baaki sab kuch bhool jao. Concrete type bhool jaane ko type erasure kehte hain. Dekho Templates and Type Erasure.
KYU kaam karta hai. Internally std::function real callable ka ek hidden pointer rakhta hai, saath mein ek chhoti table "ise kaise call karein / copy karein / destroy karein". Jab tum f(2,3) likhte ho, yeh us pointer ko follow karta hai — ek indirect call. Usse kabhi yeh jaanna nahi padta ki f actually kya hai, sirf yahi ki stored cheez int(int,int) ko answer karti hai.
TASVEER. Ek closed box jis par std::function<int(int,int)> label hai. Andar woh callable baitha hai jo tumne assign kiya; bahar ek universal call slot hai. Same box, alag guts.

Step 5 — Vector-of-callbacks ka payoff
KYA. Kyunki har std::function<void()> ka same type hota hai, tum unhe ek container mein line up kar sakte ho. Dekho Callbacks and Event Systems.
KYU matter karta hai. Ek std::vector ek element type maangta hai. Tum std::vector<lambda> nahi bana sakte kyunki koi single lambda type nahi hai (Step 1). Har ek ko std::function<void()> mein wrap karo aur sab ek hi type ban jaate hain — ab woh neatly queue mein lag jaate hain.
TASVEER. Ek vector mein identical boxes ki row; har box ek alag task chhupata hai (save / log / render). Ek loop ek ek karke har button dabaata hai.

std::vector<std::function<void()>> tasks;
tasks.push_back([]{ std::cout << "save\n"; });
tasks.push_back([]{ std::cout << "log\n"; });
for (auto& t : tasks) t(); // sab run karoStep 6 — Ab doosri machine: partial application (bind)
KYA. Do inputs wala function lo, . Ek input freeze karo, maan lo . Jo bachta hai woh ek input wala naya function hai: . Yahi freezing partial application hai, aur std::bind yahi karta hai.
KYU naaya tool. std::function store karta hai; yeh reshape nahi karta. Kabhi kabhi tumhare paas 2-argument callable hota hai lekin jo code usse call karega woh sirf 1 argument supply kar sakta hai. Tumhe missing wala pehle se yaad rakhna hoga. Bind bilkul yahi karta hai.
TASVEER. Ek 2-slot machine f(a,b). Hum 10 value ko slot a mein permanently plug kar dete hain. Ab machine mein sirf ek open slot dikhta hai — yeh ban gaya ek 1-argument machine.

Step 7 — Placeholders: baaki inputs ko wire karna
KYA. Jo slots tum open rakhte ho, unke liye placeholder _1, _2, … likhte ho. Placeholder ek routing label hai jiska matlab hai "caller ka n-th argument YAHAN daalo."
KYU blank chhodne ki jagah placeholders. Blanks ka matlab sirf "next argument in order" ho sakta tha. Placeholders zyada powerful hain: woh tumhe caller ke arguments ko reorder ya duplicate bhi karne dete hain. _1 = caller ka 1st argument, _2 = caller ka 2nd — chahे bind expression mein kaheen bhi ho.
TASVEER. Ek patch panel. Baayi taraf, woh do arguments jo caller baad mein supply karega, aur . Daayein taraf, sub(a,b) ke do slots. Coloured wires dikhate hain ki _1 aur _2 unhe kaise route karte hain — pehle seedha, phir ulta.

Step 8 — Degenerate & member cases (koi gap mat chhodo)
KYA. Hum corners cover karte hain taaki koi scenario tumhe surprise na kare.
KYU. Ek derivation tabhi trustworthy hai jab woh apne edge cases survive kare: koi placeholder nahi, saare placeholders, aur member functions ka sneaky hidden-this.
TASVEER. Teen mini-panels:
- Sab bind karo —
bind(sub,10,3)→ ek zero-argument callable,g()= 7. - Kuch bind mat karo —
bind(sub,_1,_2)→ same arity, bas ek wrapper. - Member function — object secret first argument ki tarah slide in hota hai (
this).

Ek-tasveer summary
Do machines, ek diagram: bind callable ki argument list reshape karta hai; std::function jo bhi nikle use ek uniform signature-typed roof ke neeche store karta hai, taaki use container mein daala ja sake aur call kiya ja sake.

Recall Feynman retelling — poora walkthrough seedhe alfaaz mein
Humne chaar tarah ki "jo cheezein tum call kar sako" se shuruat ki — ek plain function, lambdas, ek struct jisme () ho, ek member function — aur notice kiya ki compiler inhe alag types ki tarah dekhta hai, toh woh ek variable share nahi kar sakte (Steps 1–2). Lekin jab inhe use karte hain toh sab same feel karte hain: do ints in, ek int out. Humne us shared feeling ko signature int(int,int) naam diya (Step 3). Phir humne ek box banaya, std::function, jo real type chhupa leta hai aur sirf yahi yaad rakhta hai "mujhe signature ki tarah call kiya ja sakta hai" — yahi chhupana type erasure hai (Step 4). Kyunki har aisa box same type ka hai, hum unhe ek vector mein line up karke sab run kar sakte hain (Step 5). Phir aaya ek doosra, alag machine: bind, jo ek callable leke kuch inputs freeze karta hai, aur baad mein supply karne wale inputs kam kar deta hai — partial application (Step 6). Baaki slots placeholders _1, _2, … se wire hote hain, matlab "caller ka 1st, 2nd… argument", jo inputs reorder bhi karne deta hai (Step 7). Aakhir mein humne corners sweep kiye: saare inputs freeze karo (arity 0), kuch bhi freeze mat karo (ek plain wrapper), aur sneaky member function jiska object hidden first argument hai (Step 8). Modern C++ reshaping lambdas se karta hai — lekin box, std::function, ek unknown concrete type wale callable ko store karne ka ek sachcha tarika bana rehta hai.
Recall
Woh ek cheez kya hai jo charon callable species share karte hain aur jiske around std::function bana hai? ::: Call signature R(Args...) — usage shape, concrete type nahi.
Lambdas ke vector ko std::function kyun use karna padta hai? ::: Har lambda ka ek unique unnamed type hota hai, toh woh ek vector element type share nahi kar sakte; std::function mein wrap karne se sab ek type ban jaate hain.
std::bind(sub, 10, _1) mein, _1 kya route karta hai? ::: Caller ka pehla argument (jo bound object call hone par supply hoga), sub ke doosre parameter b mein.
Member function bind karne ke liye pehle bound argument mein kya chahiye? ::: Object (ya uska pointer) — yeh hidden this parameter fill karta hai.
bind ke through reference kaise pass karte hain? ::: std::ref(x) / std::cref(x) se wrap karo; warna bind value se copy karta hai.