Look at this piece of code:
#include <iostream> #include <functional> using namespace std; using namespace std::placeholders; void add(int a, int b, int& r) { r = a + b; } int main() { int result = 0; auto f = bind(add, _1, 20, result); f(80); cout << result << endl; return 0; }
This program supposedly adds 80 to 20 and prints the result; it compiles perfectly but when you execute it; you get…. 0!
Why?
Because the bind
method receives its parameters as parameters-by-value and the “result” variable is copied before being passed to the bound function add
. Why?
Because bind
does not know if the parameters will still be valid when the actual invocation will be performed (remember, you could pass a function
object to other function passing local variables as arguments and invoking it from there).
The solution? Pretty simple:
int main() { int result = 0; auto f = bind(add, _1, 20, ref(result)); f(80); cout << result << endl; return 0; }
I added the function ref
that sends our parameter as a reference to the bound function.
What does this function ref
do?
It is a template function that returns a reference_wrapper
object. A reference_wrapper
is a class template that wraps a reference in a concrete object.
Actually you could do something like:
int main() { int result = 0; reference_wrapper<int> result_ref(result); auto f = bind(add, _1, 20, result_ref); f(80); cout << result << endl; return 0; }
and everything would continue working as expected.
As you can see, you can pass the reference_wrapper
by value and everything will work because its copy constructor copies the reference (actually, the reference_wrapper
implementations do not store a reference but a pointer to the data being referenced, but their methods expose it as a reference).
Other nice usage of this would be in cases where you need to have a container of references (the actual objects are stored in other container or in other place and you do not need/want to have copies or pointers to them). For example, you have these classes:
class A { }; class B : public A { };
And you want to have at the same time local variables pointing to them and you want them stored in a container:
int main() { A a, c; B b, d; vector<A> v = { a, b, c, d }; }
Good? No! Bad at all! You are storing instances of class A in your vector. All the instances of B will be copied as instances of A (losing their specific attributes and all the polymorphic behavior and so on).
One solution? Storing pointers:
int main() { A a, c; B b, d; vector<A*> v = { &a, &b, &c, &d }; }
It works, but it is not evident for the user of the container if s/he will be in charge of freeing the objects or not.
Other solution? Using references:
int main() { A a, c; B b, d; vector<A&> v = { a, b, c, d }; }
Looks nice, but it does not compile; because you cannot specify reference types in a vector.
Real solution: Using reference_wrappers:
int main() { A a, c; B b, d; vector<reference_wrapper<A>> v = { a, b, c, d }; }
Someone could argue: In which scenario is this thing useful?
If you create a UI frame using Java Swing, you probably create a subclass of the JFrame class, will specify your visual components as member variables and you will also add them into the JFrame’s component list. Implementing something similar in C++ using reference_wrappers would be quite elegant.
great post as usual :) thanks a lot and keep up the good teaching :)
Thanks for your nice comments :)
Very useful, thanks a lot.
Thanks for reading :)
I know a lot from your post, please continue to provide more.
Thanks a lot! :) I will! :)