The usual way to create references is:
int x{1};
int &ref{x};There is another way to create reference objects using std::reference_wrapper template which creates a wrapper reference object to a value of type T. For example:
int x{1};
std::reference_wrapper<int> ref{x};This std::reference_wrapper has following properties:
std::reference_wrapper<T>can be implicitly converted toT&. So, when we dostd::cout << ref, asstd::reference_wrapper<T>can’t be printed, it will implicitly get converted toT&which then gets printed.std::reference_wrapper<T>::get()member function returnsT&. So,ref.get() = 10changes the value ofx.Operator=will change whatstd::reference_wrapper<T>is referencing to. For example, if we doref = ywhereyisint y{10};,refis referencing toy. Please note that we can only use lvalue for reassignment here.
For example:
// changing value of x
ref.get() = 3;
std::cout << x << "\n"; // 3
std::cout << ref << "\n"; // 3
int y{10};
ref = y;
std::cout << y << "\n"; // 10
std::cout << ref << "\n"; // 10We can also create std::reference_wrapper to reference const objects. For example:
const int x{10};
std::reference_wrapper<const int> ref{x};
ref.get() = 12; // it will fail.Furthermore, we can create const std::reference_wrapper:
const std::reference_wrapper<int> ref{x};
ref = y; // it will fail.Full example
Following is a full example of using std::reference_wrapper:
#include <iostream>
#include <functional>
int main(int argc, char const *argv[])
{
int x{1};
int y{2};
std::reference_wrapper<int> z{x};
std::cout << z << '\n';
z = y;
std::cout << z << '\n';
std::cout << "---------" << '\n';
std::cout << x << '\n';
std::cout << y << '\n';
std::cout << "---------" << '\n';
z.get() = 3;
std::cout << "---------" << '\n';
std::cout << x << '\n';
std::cout << y << '\n';
std::cout << "---------" << '\n';
return 0;
}We need <functional> header file std::reference_wrapper.
std::ref() and std::cref
Prior to C++17, we could not use CTAD and initializing reference wrapper would get long when we need to explicitly specify T as we saw in above example. So, to make this easier, std::ref() and std::cref() functions were provided.
std::ref() takes a lvalue and creates std::reference_wrapper<T>. And std::cref() creates std::reference_wrapper<const T>.
For example:
int a{1};
int b{2};
auto a_ref{std::ref(x)};
auto b_ref{std::cref(y)};So, a_ref is std::reference_wrapper<int> and b_ref is std::reference_wrapper<const int>.