What is std reference wrapper in C++?
A class template called std::reference_wrapper encapsulates a reference in an assignable, copyable object. The particular wrappers around a reference to an object or function of type T are std::reference_wrapper, CopyConstructible, and CopyAssignable. While std::reference_wrapper instances are objects that can be copied or kept in containers, they also can implicitly convert to T&, making them usable as arguments for functions that accept the underlying type by reference. With the same inputs, std::reference_wrapper can be called if the saved reference is Callable. In order to create std::reference_wrapper objects, the helper methods std::ref and std::cref are frequently utilized.
When passing objects by reference to std::bind, the std::thread constructor, or the helper methods, std::reference_wrapper is utilized for both std::make_tuple and std::make_pair. Additionally, it serves as a means of storing references inside of common containers (such as std::vector) that aren't often able to carry references. It is ensured that std::reference_wrapper is trivially copyable. T might not be a complete type.
![What is std::reference_wrapper in C++?](https://static.tutorialandexample.com/cpp/what-is-std-reference-wrapper-in-cpp1.png)
Member types:
result_type:
When T is a function, the kind of return for T. Otherwise, not specified
Argument type:
- A1 if T is a function or a reference to a function that accepts a single argument of type A1.
- Argument_type is T0*, potentially CV-qualified if T is a reference to a member function of class T0 that accepts no arguments.
- Argument_type is an alias of T if T is a class type and has a member type T::argument_type.
First_argument_type:
- The first argument is A1 if T is a function or a reference to a function that accepts two parameters of types A1 and A2.
- The first argument type is T0*, potentially CV-qualified, if T is a reference to a member function of class T0 that accepts a single argument.
- The first argument type is an alias of T, a class type, if T::first_argument_type is a member type.
Second_argument_type:
- The second argument type is A2 if T is a function or a reference to a function that accepts two arguments of types A1 and A2.
- The second argument type is A1, potentially CV-qualified if T is a reference to a member function of class T0 that accepts one argument, A1.
- The second argument type is an alias of T if T is a class type having a member type T::second argument type.
Member functions:
(constructor):
In a new instance of the std::reference_wrapper object, stores a reference.
operator=:
It rebinds a std:: reference wrapper
Get operator T&:
It retrieves the reference that is stored.
Operator ():
It invokes the function that is stored.
Non member functions:
operator==,<=>:
The reference_wrapper objects are compared to their stored references.
Possible implementation:
namespace detail
{
template<class T> constexpr T& FUN(T& t) noexcept { return t; }
template<class T> void FUN(T&&) = delete;
}
template<class T>
class reference_wrapper
{
public:
// types
using type = T;
// construct/copy/destroy
template<class U, class = decltype(
detail::FUN<T>(std::declval<U>()),
std::enable_if_t<!std::is_same_v<reference_wrapper, std::remove_cvref_t<U>>>()
)>
constexpr reference_wrapper(U&& u)
noexcept(noexcept(detail::FUN<T>(std::forward<U>(u))))
: _ptr(std::addressof(detail::FUN<T>(std::forward<U>(u)))) {}
reference_wrapper(const reference_wrapper&) noexcept = default;
// assignment
reference_wrapper& operator=(const reference_wrapper& x) noexcept = default;
// access
constexpr T& get() const noexcept { return *_ptr; }
template<class... ArgTypes>
constexpr std::invoke_result_t<T&, ArgTypes...>
operator() (ArgTypes&&... args ) const
noexcept(std::is_nothrow_invocable_v<T&, ArgTypes...>)
{
return std::invoke(get(), std::forward<ArgTypes>(args)...);
}
private:
T* _ptr;
};
// deduction guides
template<class T>
reference_wrapper(T&) -> reference_wrapper<T>;
Example:
Let us take an example to illustrate the Std::reference_wrapper in C++.
Run this code
#include <algorithm>
#include <functional>
#include <iostream>
#include <list>
#include <numeric>
#include <random>
#include <vector>
void println(auto const rem, std::ranges::range auto const& v)
{
for (std::cout << rem; auto const& e : v)
std::cout << e << ' ';
std::cout << '\n';
}
int main()
{
std::list<int> l(10);
std::iota(l.begin(), l.end(), -4);
// can't use shuffle on a list (requires random access), but can use it on a vector
std::vector<std::reference_wrapper<int>> v(l.begin(), l.end());
std::ranges::shuffle(v, std::mt19937{std::random_device{}()});
println("Contents of the list: ", l);
println("The list's contents as seen by a vector that has been shuffled: ", v);
std::cout << "Doubling values in initial list..\n";
std::ranges::for_each(l, [](int& i) { i *= 2; });
println("Contents of list, seen shuffled vector: ", v);
}
Output:
Contents of the list: -4 -3 -2 -1 0 1 2 3 4 5
Contents of the list, as seen through a shuffled vector: -1 2 -2 1 5 0 3 -3 -4 4
Doubling the values in the initial list...
Contents of the list, as seen through a shuffled vector: -2 4 -4 2 10 0 6 -6 -8 8
Conclusion:
In conclusion, the objects can be passed to std::bind by reference, and references can be stored in standard containers using a reference wrapper. A static assert will fail at compilation time if Ty is not an object type or function type.est degree in the degree sequence is removed repeatedly, and the matching vertex is added to the graph to connect it to its neighbors.lity of the code.