The History of std::bind
Before C++11, function objects and function pointers were the primary way to encapsulate callable logic. However, they were often verbose and not flexible enough for dynamically setting arguments.
Boost.Bind: The Predecessor
Before std::bind
made its way into the C++11 standard, Boost.Bind was the go-to library for function binding. It allowed programmers to:
- Partially apply function arguments.
- Swap the order of parameters dynamically.
- Create callable objects from functions and function objects.
Why Was std::bind
Introduced?
- Boost was popular, but not standard → The C++ committee wanted a built-in solution.
- More readable function composition → Less need for custom function objects.
- Better integration with
std::function
→ Creating callable objects dynamically became easier.
Key Innovations of std::bind
✅ Standardized in C++11 → Built into <functional>
, removing dependency on Boost.
✅ Enables Partial Function Application → Pre-set some arguments, leaving others flexible.
✅ Works with Member Functions → Allows method binding on objects.
✅ Thread-Safe Callbacks → Great for multi-threaded programming and event-driven designs.
Further Reading:
std::bind
vs. Modern C++ Alternatives
Feature | std::bind | Modern Alternative |
---|
Partial Function Application | ✅ Yes | ✅ Lambda Functions |
Works with Function Pointers | ✅ Yes | ✅ Lambda Functions |
Works with Member Functions | ✅ Yes | ✅ Lambda Functions |
Readability | ❌ Less Readable | ✅ Lambda Functions |
Performance | ✅ Efficient | ✅ Even Better with Lambdas |
std::bind` is still useful, but lambda functions have mostly replaced it in modern C++.
std::bind
Syntax Table
Concept | std::bind Code | Equivalent in Lambda |
---|
Bind Function | auto f = std::bind(foo, _1, _2); | auto f = [](int a, int b) { foo(a, b); }; |
Bind Member Function | auto f = std::bind(&MyClass::method, obj, _1); | auto f = [&](int x) { obj.method(x); }; |
Bind with Fixed Argument | auto f = std::bind(foo, 42, _1); | auto f = [](int x) { foo(42, x); }; |
Bind with Rearranged Arguments | auto f = std::bind(foo, _2, _1); | auto f = [](int a, int b) { foo(b, a); }; |
Thread-Safe Callback | std::thread t(std::bind(foo, 42)); | std::thread t([]{ foo(42); }); |
C++ std::bind
Examples
std::bind
is a powerful utility in C++ that allows binding functions with specific arguments, placeholders, and even member functions. Below are 10 examples demonstrating different use cases of std::bind
.
1. Binding a Free Function with Fixed Arguments
You can use std::bind
to create a new function with some arguments already set.
1
2
3
4
5
6
7
8
9
10
11
12
| #include <iostream>
#include <functional>
void greet(const std::string& name) {
std::cout << "Hello, " << name << "!" << std::endl;
}
int main() {
auto greetAlice = std::bind(greet, "Alice");
greetAlice(); // Output: Hello, Alice!
return 0;
}
|
2. Binding a Function with a Placeholder
Using placeholders allows you to bind some arguments while keeping others dynamic.
1
2
3
4
5
6
7
8
9
10
11
12
| #include <iostream>
#include <functional>
void add(int a, int b) {
std::cout << a + b << std::endl;
}
int main() {
auto addFive = std::bind(add, 5, std::placeholders::_1);
addFive(10); // Output: 15
return 0;
}
|
3. Binding a Member Function to an Object
You can bind a member function to a specific instance of a class.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| #include <iostream>
#include <functional>
class Calculator {
public:
int multiply(int a, int b) {
return a * b;
}
};
int main() {
Calculator calc;
auto multiplyByTwo = std::bind(&Calculator::multiply, &calc, 2, std::placeholders::_1);
std::cout << multiplyByTwo(5) << std::endl; // Output: 10
return 0;
}
|
4. Reordering Function Arguments
Using placeholders, you can swap argument positions.
1
2
3
4
5
6
7
8
9
10
11
12
| #include <iostream>
#include <functional>
void subtract(int a, int b) {
std::cout << a - b << std::endl;
}
int main() {
auto reverseSubtract = std::bind(subtract, std::placeholders::_2, std::placeholders::_1);
reverseSubtract(10, 20); // Output: 10
return 0;
}
|
5. Using std::bind
with Standard Algorithms
You can use std::bind
with STL algorithms like std::count_if
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| #include <iostream>
#include <functional>
#include <vector>
#include <algorithm>
bool isEven(int n) {
return n % 2 == 0;
}
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5, 6};
auto countEven = std::count_if(numbers.begin(), numbers.end(), std::bind(isEven, std::placeholders::_1));
std::cout << countEven << std::endl; // Output: 3
return 0;
}
|
6. Binding a Member Function with a Specific Object
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| #include <iostream>
#include <functional>
class Printer {
public:
void printMessage(const std::string& message) {
std::cout << message << std::endl;
}
};
int main() {
Printer printer;
auto printHello = std::bind(&Printer::printMessage, &printer, "Hello, World!");
printHello(); // Output: Hello, World!
return 0;
}
|
7. Binding a Function with Multiple Placeholders
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| #include <iostream>
#include <functional>
void divide(int a, int b) {
if (b != 0)
std::cout << a / b << std::endl;
else
std::cout << "Division by zero!" << std::endl;
}
int main() {
auto divideBy = std::bind(divide, std::placeholders::_1, std::placeholders::_2);
divideBy(10, 2); // Output: 5
divideBy(10, 0); // Output: Division by zero!
return 0;
}
|
8. Binding a Member Function to Different Objects
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| #include <iostream>
#include <functional>
class Counter {
public:
void increment(int& value) {
++value;
}
};
int main() {
Counter counter;
int a = 5;
int b = 10;
auto incrementA = std::bind(&Counter::increment, &counter, std::ref(a));
auto incrementB = std::bind(&Counter::increment, &counter, std::ref(b));
incrementA();
incrementB();
std::cout << a << ", " << b << std::endl; // Output: 6, 11
return 0;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| #include <iostream>
#include <functional>
#include <vector>
#include <algorithm>
int multiplyBy(int a, int factor) {
return a * factor;
}
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5};
std::vector<int> results(numbers.size());
auto multiplyByThree = std::bind(multiplyBy, std::placeholders::_1, 3);
std::transform(numbers.begin(), numbers.end(), results.begin(), multiplyByThree);
for (int n : results) {
std::cout << n << " "; // Output: 3 6 9 12 15
}
std::cout << std::endl;
return 0;
}
|
10. Binding a Function to a Thread
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| #include <iostream>
#include <functional>
#include <thread>
void threadFunction(int a, int b) {
std::cout << "Sum from thread: " << a + b << std::endl;
}
int main() {
auto boundFunction = std::bind(threadFunction, 5, 10);
std::thread t(boundFunction);
t.join(); // Output: Sum from thread: 15
return 0;
}
|
Key Takeaways
std::bind
is useful for partial function application and dynamic function binding.- It replaced Boost.Bind in modern C++, but lambda functions have largely made it obsolete.
- It’s still valuable in scenarios like threading, callbacks, and function pointers.
References
- std::bind - C++ Reference
- Boost.Bind Documentation
- C++ Lambda Expressions