Difference between revisions of "cpp/utility/functional/reference wrapper"
m (fmt) |
m (→Member types: fmt: +br=yes) |
||
(7 intermediate revisions by 4 users not shown) | |||
Line 9: | Line 9: | ||
{{dcl end}} | {{dcl end}} | ||
− | {{tt|std::reference_wrapper}} is a class template that wraps a reference in a copyable, assignable object | + | {{tt|std::reference_wrapper}} is a class template that wraps a reference in a copyable, assignable object. |
Specifically, {{tt|std::reference_wrapper}} is a {{named req|CopyConstructible}} and {{named req|CopyAssignable}} wrapper around a reference to object or reference to function of type {{tt|T}}. Instances of {{tt|std::reference_wrapper}} are objects (they can be copied or stored in containers) but they are implicitly convertible to {{c|T&}}, so that they can be used as arguments with the functions that take the underlying type by reference. | Specifically, {{tt|std::reference_wrapper}} is a {{named req|CopyConstructible}} and {{named req|CopyAssignable}} wrapper around a reference to object or reference to function of type {{tt|T}}. Instances of {{tt|std::reference_wrapper}} are objects (they can be copied or stored in containers) but they are implicitly convertible to {{c|T&}}, so that they can be used as arguments with the functions that take the underlying type by reference. | ||
Line 17: | Line 17: | ||
Helper functions {{lc|std::ref}} and {{lc|std::cref}} are often used to generate {{tt|std::reference_wrapper}} objects. | Helper functions {{lc|std::ref}} and {{lc|std::cref}} are often used to generate {{tt|std::reference_wrapper}} objects. | ||
− | {{tt|std::reference_wrapper}} is | + | {{tt|std::reference_wrapper}} is used to pass objects by reference to {{lc|std::bind}}, the constructor of {{lc|std::thread}}, or the helper functions {{lc|std::make_pair}} and {{lc|std::make_tuple}}. It can also be used as a mechanism to store references inside standard containers (like {{lc|std::vector}}) that cannot normally hold references. |
{{rrev|since=c++17| | {{rrev|since=c++17| | ||
Line 31: | Line 31: | ||
{{dsc hitem|type|definition}} | {{dsc hitem|type|definition}} | ||
{{dsc|{{tt|type}}|{{tt|T}}}} | {{dsc|{{tt|type}}|{{tt|T}}}} | ||
− | {{dsc|{{tt|result_type}}<br>{{mark life|deprecated=c++17|removed=c++20}}|The return type of {{tt|T}} if {{tt|T}} is a function. Otherwise, not defined}} | + | {{dsc|{{tt|result_type}}<br>{{mark life|deprecated=c++17|removed=c++20|br=yes}}|The return type of {{tt|T}} if {{tt|T}} is a function. Otherwise, not defined.}} |
− | {{dsc|{{tt|argument_type}}<br>{{mark life|deprecated=c++17|removed=c++20}}| | + | {{dsc|{{tt|argument_type}}<br>{{mark life|deprecated=c++17|removed=c++20|br=yes}}| |
− | * if {{tt|T}} is a function or pointer to function that takes one argument of type {{tt|A1}}, | + | * if {{tt|T}} is a function or pointer to function that takes one argument of type {{tt|A1}}, then {{tt|argument_type}} is {{tt|A1}}<br> |
− | * if {{tt|T}} is a pointer to member function of class {{tt|T0}} that takes no arguments, then {{tt|argument_type}} is {{ | + | * if {{tt|T}} is a pointer to member function of class {{tt|T0}} that takes no arguments, then {{tt|argument_type}} is {{c/core|T0*}}, possibly cv-qualified<br> |
− | * if {{tt|T}} is a class type with a member type {{ | + | * if {{tt|T}} is a class type with a member type {{c/core|T::argument_type}}, then {{tt|argument_type}} is an alias of that}} |
− | {{dsc|{{tt|first_argument_type}}<br>{{mark life|deprecated=c++17|removed=c++20}}| | + | {{dsc|{{tt|first_argument_type}}<br>{{mark life|deprecated=c++17|removed=c++20|br=yes}}| |
− | * if {{tt|T}} is a function or pointer to function that takes two arguments of types {{tt|A1}} and {{tt|A2}}, then {{tt|first_argument_type}} is {{tt|A1}} | + | * if {{tt|T}} is a function or pointer to function that takes two arguments of types {{tt|A1}} and {{tt|A2}}, then {{tt|first_argument_type}} is {{tt|A1}}<br> |
− | * if {{tt|T}} is a pointer to member function of class {{tt|T0}} that takes one argument, then {{tt|first_argument_type}} is {{ | + | * if {{tt|T}} is a pointer to member function of class {{tt|T0}} that takes one argument, then {{tt|first_argument_type}} is {{c/core|T0*}}, possibly cv-qualified<br> |
− | * if {{tt|T}} is a class type with a member type {{ | + | * if {{tt|T}} is a class type with a member type {{c/core|T::first_argument_type}}, then {{tt|first_argument_type}} is an alias of that |
}} | }} | ||
− | {{dsc|{{tt|second_argument_type}}<br>{{mark life|deprecated=c++17|removed=c++20}}| | + | {{dsc|{{tt|second_argument_type}}<br>{{mark life|deprecated=c++17|removed=c++20|br=yes}}| |
* if {{tt|T}} is a function or pointer to function that takes two arguments of type s {{tt|A1}} and {{tt|A2}}, then {{tt|second_argument_type}} is {{tt|A2}}<br> | * if {{tt|T}} is a function or pointer to function that takes two arguments of type s {{tt|A1}} and {{tt|A2}}, then {{tt|second_argument_type}} is {{tt|A2}}<br> | ||
* if {{tt|T}} is a pointer to member function of class {{tt|T0}} that takes one argument {{tt|A1}}, then {{tt|second_argument_type}} is {{tt|A1}}, possibly cv-qualified<br> | * if {{tt|T}} is a pointer to member function of class {{tt|T0}} that takes one argument {{tt|A1}}, then {{tt|second_argument_type}} is {{tt|A1}}, possibly cv-qualified<br> | ||
− | * if {{tt|T}} is a class type with a member type {{ | + | * if {{tt|T}} is a class type with a member type {{c/core|T::second_argument_type}}, then {{tt|second_argument_type}} is an alias of that}} |
{{dsc end}} | {{dsc end}} | ||
Line 53: | Line 53: | ||
{{dsc inc|cpp/utility/functional/reference_wrapper/dsc get}} | {{dsc inc|cpp/utility/functional/reference_wrapper/dsc get}} | ||
{{dsc inc|cpp/utility/functional/reference_wrapper/dsc operator()}} | {{dsc inc|cpp/utility/functional/reference_wrapper/dsc operator()}} | ||
+ | {{dsc end}} | ||
+ | |||
+ | ===Non-member functions=== | ||
+ | {{dsc begin}} | ||
+ | {{dsc inc|cpp/utility/functional/reference_wrapper/dsc operator_cmp}} | ||
{{dsc end}} | {{dsc end}} | ||
==={{rl|deduction guides|Deduction guides}}{{mark since c++17}}=== | ==={{rl|deduction guides|Deduction guides}}{{mark since c++17}}=== | ||
+ | |||
+ | ===Helper classes=== | ||
+ | {{dsc begin}} | ||
+ | {{dsc inc|cpp/utility/functional/reference_wrapper/dsc basic_common_reference}} | ||
+ | {{dsc end}} | ||
===Possible implementation=== | ===Possible implementation=== | ||
{{eq fun | {{eq fun | ||
|1= | |1= | ||
− | namespace detail { | + | namespace detail |
− | template <class T> constexpr T& FUN(T& t) noexcept { return t; } | + | { |
− | template <class T> void FUN(T&&) = delete; | + | template<class T> constexpr T& FUN(T& t) noexcept { return t; } |
+ | template<class T> void FUN(T&&) = delete; | ||
} | } | ||
− | template <class T> | + | template<class T> |
class reference_wrapper | class reference_wrapper | ||
{ | { | ||
Line 73: | Line 84: | ||
// construct/copy/destroy | // construct/copy/destroy | ||
− | template <class U, class = decltype( | + | template<class U, class = decltype( |
detail::FUN<T>(std::declval<U>()), | detail::FUN<T>(std::declval<U>()), | ||
std::enable_if_t<!std::is_same_v<reference_wrapper, std::remove_cvref_t<U>>>() | std::enable_if_t<!std::is_same_v<reference_wrapper, std::remove_cvref_t<U>>>() | ||
Line 90: | Line 101: | ||
constexpr T& get() const noexcept { return *_ptr; } | constexpr T& get() const noexcept { return *_ptr; } | ||
− | template< class... ArgTypes > | + | template<class... ArgTypes> |
constexpr std::invoke_result_t<T&, ArgTypes...> | constexpr std::invoke_result_t<T&, ArgTypes...> | ||
− | operator() ( ArgTypes&&... args ) const | + | operator() (ArgTypes&&... args ) const |
noexcept(std::is_nothrow_invocable_v<T&, ArgTypes...>) | noexcept(std::is_nothrow_invocable_v<T&, ArgTypes...>) | ||
{ | { | ||
Line 109: | Line 120: | ||
===Example=== | ===Example=== | ||
{{example | {{example | ||
− | |Demonstrates the use of {{tt|std::reference_wrapper}} as a container of references, which makes it possible to access the same container using multiple | + | |Demonstrates the use of {{tt|std::reference_wrapper}} as a container of references, which makes it possible to access the same container using multiple indices. |
|code= | |code= | ||
#include <algorithm> | #include <algorithm> | ||
Line 119: | Line 130: | ||
#include <vector> | #include <vector> | ||
− | void | + | void println(auto const rem, std::ranges::range auto const& v) |
{ | { | ||
for (std::cout << rem; auto const& e : v) | for (std::cout << rem; auto const& e : v) | ||
Line 136: | Line 147: | ||
std::ranges::shuffle(v, std::mt19937{std::random_device{}()}); | std::ranges::shuffle(v, std::mt19937{std::random_device{}()}); | ||
− | + | println("Contents of the list: ", l); | |
− | + | println("Contents of the list, as seen through a shuffled vector: ", v); | |
std::cout << "Doubling the values in the initial list...\n"; | std::cout << "Doubling the values in the initial list...\n"; | ||
std::ranges::for_each(l, [](int& i) { i *= 2; }); | std::ranges::for_each(l, [](int& i) { i *= 2; }); | ||
− | + | println("Contents of the list, as seen through a shuffled vector: ", v); | |
} | } | ||
|p=true | |p=true |
Latest revision as of 02:04, 8 July 2024
Defined in header <functional>
|
||
template< class T > class reference_wrapper; |
(since C++11) | |
std::reference_wrapper
is a class template that wraps a reference in a copyable, assignable object.
Specifically, std::reference_wrapper
is a CopyConstructible and CopyAssignable wrapper around a reference to object or reference to function of type T
. Instances of std::reference_wrapper
are objects (they can be copied or stored in containers) but they are implicitly convertible to T&, so that they can be used as arguments with the functions that take the underlying type by reference.
If the stored reference is Callable, std::reference_wrapper
is callable with the same arguments.
Helper functions std::ref and std::cref are often used to generate std::reference_wrapper
objects.
std::reference_wrapper
is used to pass objects by reference to std::bind, the constructor of std::thread, or the helper functions std::make_pair and std::make_tuple. It can also be used as a mechanism to store references inside standard containers (like std::vector) that cannot normally hold references.
|
(since C++17) |
|
(since C++20) |
Contents |
[edit] Member types
type | definition |
type
|
T
|
result_type (deprecated in C++17) (removed in C++20) |
The return type of T if T is a function. Otherwise, not defined.
|
argument_type (deprecated in C++17) (removed in C++20) |
|
first_argument_type (deprecated in C++17) (removed in C++20) |
|
second_argument_type (deprecated in C++17) (removed in C++20) |
|
[edit] Member functions
stores a reference in a new std::reference_wrapper object (public member function) | |
rebinds a std::reference_wrapper (public member function) | |
accesses the stored reference (public member function) | |
calls the stored function (public member function) |
[edit] Non-member functions
(C++26) |
compares reference_wrapper objects as their stored references (function) |
[edit] Deduction guides(since C++17)
[edit] Helper classes
determines the common reference type of reference_wrapper and non-reference_wrapper (class template specialization) |
[edit] 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 operator T& () const noexcept { return *_ptr; } 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>; |
[edit] Example
Demonstrates the use of std::reference_wrapper
as a container of references, which makes it possible to access the same container using multiple indices.
#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("Contents of the list, as seen through a shuffled vector: ", v); std::cout << "Doubling the values in the initial list...\n"; std::ranges::for_each(l, [](int& i) { i *= 2; }); println("Contents of the list, as seen through a shuffled vector: ", v); }
Possible 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
[edit] See also
(C++11)(C++11) |
creates a std::reference_wrapper with a type deduced from its argument (function template) |
(C++11) |
binds one or more arguments to a function object (function template) |
(C++20)(C++20) |
get the reference type wrapped in std::reference_wrapper (class template) |