This small program:
#include <iostream>
#include <functional>
void add(int a, int b, int& r)
{
r = a + b;
}
int main()
{
int result = 0;
using namespace std::placeholders;
auto f = std::bind(add, _1, 20, result);
f(80);
std::cout << result << std::endl;
return 0;
}
Supposedly adds 80 to 20 and prints the result; it compiles perfectly but when it gets executed it; it prints out…. 0!
Why?
Because the std::bind method parameters are passed using value semantics and, thus, the “result” variable is copied before being passed to the bound function add. Why?
Because since std::bind does not know if the parameters will still be valid when the actual invocation is performed (programmers could pass a std::function object to another function passing local variables as arguments and invoking it from there).
The solution? Pretty simple:
int main()
{
int result = 0;
auto f = std::bind(add, _1, 20, std::ref(result));
f(80);
std::cout << result << std::endl;
return 0;
}
The function std::ref was used, which sends the parameter as a reference to the bound function.
What does this function std::ref do?
It is a template function that returns a std::reference_wrapper object. A std::reference_wrapper is a class template that wraps a reference in a concrete object.
It can also be done in this way:
int main()
{
int result = 0;
std::reference_wrapper<int> result_ref(result);
auto f = std::bind(add, _1, 20, result_ref);
f(80);
std:.cout << result << std::endl;
return 0;
}
and everything would continue working as expected.
As it can be seen, programmers can pass a std::reference_wrapper by value, and everything will work properly because its copy constructor copies the reference (actually, the std::reference_wrapper implementations do not store a reference but a pointer to the data being referenced, but their methods expose it as an actual reference).
Other nice use of this would be in cases where programmers need to have a container of references (the actual objects are stored in other container or elsewhere, and programmers do not need or want to have copies or pointers to them). For example, having these classes:
class A { };
class B : public A { };
If programmers want to have local variables pointing to these objects and store such variables in a container:
int main()
{
A a, c;
B b, d;
std::vector<A> v = { a, b, c, d };
}
Good? No! Bad at all! The programmers here are storing instances of class A in the vector. All instances of B will be copied as instances of A (losing their specific attributes, methods, and all the polymorphic behavior they could have, and so on).
One solution? Storing pointers:
int main()
{
A a, c;
B b, d;
std::vector<A*> v = { &a, &b, &c, &d };
}
It works, but it is not clear whether the container consumers will be responsible for freeing the objects.
Other solution? Using references:
int main()
{
A a, c;
B b, d;
std::vector<A&> v = { a, b, c, d };
}
Looks nice, but it does not compile; because programmers cannot specify reference types in a vector.
Real solution: Using std::reference_wrapper:
int main()
{
A a, c;
B b, d;
std::vector<std::reference_wrapper<A>> v = { a, b, c, d };
}
Someone could argue: In what scenario is this thing useful?
If some developers are creating a UI frame using Java Swing, they probably create a subclass of the JFrame class, specify their visual components as member variables, and also add them to the JFrame‘s component list. Implementing something similar in C++ using std::reference_wrapper instances would be quite elegant.