I am trying to understand std::reference_wrapper
.
The following code shows that the reference wrapper does not behave exactly like a reference.
#include <iostream> #include <vector> #include <functional> int main() { std::vector<int> numbers = {1, 3, 0, -8, 5, 3, 1}; auto referenceWrapper = std::ref(numbers); std::vector<int>& reference = numbers; std::cout << reference[3] << std::endl; std::cout << referenceWrapper.get()[3] << std::endl; // I need to use get ^ // otherwise does not compile. return 0; }
If I understand it correctly, the implicit conversion does not apply to calling member functions. Is this an inherent limitation? Do I need to use the std::reference_wrapper::get
so often?
Another case is this:
#include <iostream> #include <functional> int main() { int a = 3; int b = 4; auto refa = std::ref(a); auto refb = std::ref(b); if (refa < refb) std::cout << "success" << std::endl; return 0; }
This works fine, but when I add this above the main
definition:
template <typename T> bool operator < (T left, T right) { return left.someMember(); }
The compiler tries to instantiate the template and forgets about implicit conversion and the built in operator.
Is this behavior inherent or am I misunderstanding something crucial about the std::reference_wrapper
?
A reference_wrapper<Ty> is a copy constructible and copy assignable wrapper around a reference to an object or a function of type Ty , and holds a pointer that points to an object of that type. A reference_wrapper can be used to store references in standard containers, and to pass objects by reference to std::bind .
std::reference_wrapper is a class template that wraps a reference in a copyable, assignable object. It is frequently used as a mechanism to store references inside standard containers (like std::vector) which cannot normally hold references.
No, you cannot do this reliably in C++03, because the constructor of pair takes references to T , and creating a reference to a reference is not legal in C++03.
Class std::reference_wrapper<T>
implements an implicit converting operator to T&
:
operator T& () const noexcept;
and a more explicit getter:
T& get() const noexcept;
The implicit operator is called when a T
(or T&
) is required. For instance
void f(some_type x); // ... std::reference_wrapper<some_type> x; some_type y = x; // the implicit operator is called f(x); // the implicit operator is called and the result goes to f.
However, sometimes a T
is not necessarily expected and, in this case, you must use get
. This happens, mostly, in automatic type deduction contexts. For instance,
template <typename U> g(U x); // ... std::reference_wrapper<some_type> x; auto y = x; // the type of y is std::reference_wrapper<some_type> g(x); // U = std::reference_wrapper<some_type>
To get some_type
instead of std::reference_wrapper<some_type>
above you should do
auto y = x.get(); // the type of y is some_type g(x.get()); // U = some_type
Alternativelly the last line above could be replaced by g<some_type>(x);
. However, for templatized operators (e.g. ostream::operator <<()
) I believe you can't explicit the type.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With