A function in C++ is normally just a name you call directly. But sometimes you want to store a callable in a variable , pass it around, swap it later, or keep a list of "things to do". std::function is a type-erased wrapper that can hold any callable (free function, lambda, functor, member function pointer) as long as the call signature matches. std::bind is a tool that pre-fills some arguments of a callable, producing a new callable with fewer (or reordered) arguments — this is called partial application .
C++ has many kinds of callables, and they all have different types :
A free function int(int,int) has type int(*)(int,int).
Each lambda has its own unique unnamed type .
A functor is a class with operator().
A member function needs an object to be called on.
You can't put these different types in one container or one variable. std::function<R(Args...)> gives them all one uniform type based only on the signature R(Args...).
Intuition Type erasure in one line
"I don't care what you are; I only care that I can call you like f(a,b) and get back an R." That promise is the signature. std::function erases everything else.
std::function<R(Args...)> is a class template that stores, copies, and invokes any callable whose call is compatible with signature R(Args...). An empty std::function calls nothing; invoking it throws std::bad_function_call.
Worked example Storing four different callables in ONE type
#include <functional>
#include <iostream>
int add ( int a , int b ) { return a + b; } // free function
struct Mul { int operator () ( int a , int b ) const { return a * b; } }; // functor
int main () {
std ::function <int ( int , int ) > f; // empty
f = add; // Why? signature int(int,int) matches
std ::cout << f ( 2 , 3 ) << " \n " ; // 5
f = []( int a , int b ){ return a - b; }; // Why? lambda with same signature
std ::cout << f ( 2 , 3 ) << " \n " ; // -1
f = Mul{}; // Why? functor's operator() matches
std ::cout << f ( 2 , 3 ) << " \n " ; // 6
}
Why this works: all three are callable as int(int,int). std::function only checks the call shape, not the underlying type.
Worked example A vector of callbacks (the killer use-case)
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 (); // run every task
Why this step? You can't make a vector of lambdas directly because each lambda is a different type. std::function<void()> unifies them.
std::bind(callable, a1, a2, ...) produces a new callable where you fix some arguments now and leave others as placeholders (std::placeholders::_1, _2, ...) to be supplied later.
Intuition WHAT bind really does (partial application)
Suppose you have f ( x , y ) f(x,y) f ( x , y ) . Binding x = 10 x=10 x = 10 gives a new function g ( y ) = f ( 10 , y ) g(y)=f(10,y) g ( y ) = f ( 10 , y ) . You reduced the number of inputs by remembering one. Placeholders let you keep, drop, or reorder the remaining inputs.
When you later call the bound object with arguments ( c 1 , c 2 , … ) (c_1, c_2, \dots) ( c 1 , c 2 , … ) :
A fixed value in the bind expression is used as-is.
A placeholder _n is replaced by the n-th call argument c n c_n c n .
Worked example Fixing one argument
using namespace std :: placeholders ;
int sub ( int a , int b ){ return a - b; }
auto sub10 = std :: bind (sub, 10 , _1); // a=10 fixed, b=_1
sub10 ( 3 ); // -> sub(10,3) = 7
Why? 10 fills a; _1 says "put the first call arg into b". So sub10(3) becomes sub(10,3).
Worked example Reordering arguments
auto flip = std :: bind (sub, _2, _1); // swap order
flip ( 3 , 10 ); // -> sub(10,3) = 7
Why? _2 is the 2nd call arg (10) → goes to a. _1 is the 1st (3) → goes to b. So we call sub(10,3).
Worked example Binding a member function
struct Counter {
int base;
int addBase ( int x ) const { return base + x; }
};
Counter c{ 100 };
auto f = std :: bind ( & Counter ::addBase, & c, _1); // pass object as 1st arg
f ( 5 ); // -> c.addBase(5) = 105
Why this step? A member function secretly takes this as its first parameter. So bind treats the object (or pointer) as the first bound argument.
Intuition 80/20: what you actually need
95% of real code uses lambdas instead of std::bind — they're clearer and faster. std::function is still essential for storing callbacks of unknown concrete type . Learn std::function deeply; learn std::bind enough to read old code.
Worked example Same thing, both ways
auto a = std :: bind (sub, 10 , _1); // old style
auto b = []( int y ){ return sub ( 10 ,y); }; // modern, clearer
Common mistake "std::function is free / zero-cost like a function pointer."
Why it feels right: it looks like a thin wrapper. Reality: it may heap-allocate to store large callables and uses a virtual call / indirect call to invoke them — it can't be inlined. Fix: for hot loops prefer templates (template<class F> void run(F f)) or auto; use std::function only when you truly need a stored uniform type.
Common mistake "_1 means the first bound value."
Why it feels right: "1 = first thing in the list." Reality: _1 is the first argument of the later call , not a position in the bind list. Fix: read _n as "the n-th argument the user passes when calling the bound object."
Common mistake "bind captures references by default."
Why it feels right: lambdas can capture by reference, so people assume bind does too. Reality: std::bind copies its arguments by value. To pass a reference you must wrap with std::ref(x) (or std::cref). Fix: std::bind(f, std::ref(obj), _1).
Recall Feynman: explain to a 12-year-old
Imagine a TV remote (std::function). It has buttons of a fixed shape (the signature). You don't care if the remote talks to a Sony or a Samsung TV — pressing the button just works. std::function is a remote that can be pointed at any "TV" (function, lambda, etc.) that understands the same buttons.
Now std::bind is like pre-setting a button : you have a volume button that takes "which TV" and "how loud". You stick a label "always the living-room TV" on it, so now the button only asks "how loud?". You've remembered part of the answer in advance.
"FUNCTION = uniform remote; BIND = pre-pressed button."
For placeholders: "_n = the n-th arg the caller gives later."
What does std::function<R(Args...)> store? Any callable (free fn, lambda, functor, member fn) whose call matches signature R(Args...), via type erasure.
Why can't you put two different lambdas in the same variable directly? Each lambda has its own unique unnamed type; std::function unifies them under one signature-based type.
What happens when you call an empty std::function? It throws std::bad_function_call.
What does std::bind do conceptually? Partial application: fixes some arguments now, leaves placeholders for the rest, producing a new callable.
What does the placeholder _2 mean? The second argument supplied when the bound object is later called (not the 2nd item in the bind list).
How do you pass an argument by reference to std::bind? Wrap it in std::ref(x) (or std::cref(x)); bind copies by value otherwise.
How do you bind a member function addBase of object c? std::bind(&Counter::addBase, &c, _1) — the object/pointer is the first bound argument (the implicit this).
Why is std::function not zero-cost? It may heap-allocate and uses an indirect/virtual call, so it can't be inlined like a direct call.
Modern preference: bind or lambda? Lambda — clearer and usually faster; bind mostly survives in legacy code.
Give the bind expression that swaps args of sub(a,b). std::bind(sub, _2, _1).
Lambda Expressions — the modern replacement for most std::bind uses
Function Pointers — the low-level callable std::function can wrap
Functors and operator() — class-based callables
Templates and Type Erasure — the mechanism behind std::function
Callbacks and Event Systems — primary real-world use of std::function
std::ref and std::cref — needed to pass references through bind
Empty throws bad_function_call
std::bind partial application
Intuition Hinglish mein samjho
Dekho, C++ me normally function ko hum direct call karte hain. Lekin kabhi aisa hota hai ki hume function ko ek variable me store karna hota hai, ya ek list me daalna hota hai (jaise "ye sab kaam baad me karne hain"). Problem ye hai ki har callable ka type alag hota hai — free function ka alag, har lambda ka apna unique type, functor ka alag. Inko ek hi container me daalna mushkil hai. Yahin std::function<R(Args...)> aata hai: ye ek uniform wrapper hai jo bolta hai "mujhe matlab nahi tu kaun hai, bas tujhe f(a,b) ki tarah call kar saku aur R mile" — isi ko type erasure kehte hain.
std::bind ka kaam hai partial application . Maan lo function hai sub(a,b). Agar tum a=10 fix kar do to ek naya function ban jaata hai g(b) = sub(10,b). Placeholders _1, _2 batate hain ki baaki arguments kahan jayenge. Yaad rakho: _1 ka matlab hai "jab user baad me bound object ko call karega, uska pehla argument" — ye bind list ka position nahi hai. Aur _2, _1 likh ke tum arguments ka order bhi swap kar sakte ho.
Do important traps: pehla, std::bind arguments ko copy karta hai, reference chahiye to std::ref(x) use karo. Doosra, empty std::function ko call karoge to std::bad_function_call throw hota hai, isliye if(f) f(); check karo. Aur ek aur baat — std::function zero-cost nahi hai, ye heap allocate kar sakta hai aur indirect call use karta hai, to hot loops me templates ya auto lambda better hai.
Modern advice (80/20): aaj kal std::bind ki jagah lambda use karo, zyada clear aur fast hota hai. std::function zaroor seekho kyunki callbacks aur event systems me bahut kaam aata hai. Bind ko sirf itna seekho ki purana code padh sako. Mantra: "FUNCTION = universal remote, BIND = pehle se dabaya hua button."