std::unwrap_reference, std::unwrap_ref_decay
From cppreference.com
 
 
 < cpp | utility | functional 
 
 
 C++ 
 Feature test macros (C++20)
 Concepts library (C++20)
 Metaprogramming library (C++11)
 Ranges library (C++20)
 Filesystem library (C++17)
 Concurrency support library (C++11)
 Execution control library (C++26)
Utilities library 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  
Relational operators (deprecated in C++20) Integer comparison functions  
 
 
 
 Swap and type operations  Common vocabulary types 
 Type support (basic types, RTTI)
 Library feature-test macros (C++20)
(C++11)
(C++20)
(C++26)
(C++20)
 Coroutine support (C++20)
 Contract support (C++26)
(C++20)(C++20)
(C++20)
(C++20)
(C++20)
(C++20)
(C++20)
(C++20)
(C++20)
(C++20)
(C++20)
(C++20)
(C++20)
(C++20)
  (C++20)(C++20)(C++20)
  (C++20)(C++20)(C++20)
 General utilities
(C++20)(C++20)(C++20)
  (C++20)(C++20)(C++20)
(C++20)
Function objects 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Old binders and adaptors  
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
(C++11)
(C++23)
(C++26)
(C++26)
(C++11)
(C++11)
(C++20)(C++23)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)(C++11)
unwrap_referenceunwrap_ref_decay
(C++20)(C++20)
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)
(C++14)
(C++17)
(C++17)
(C++17)
(C++17)    
(C++20)
(C++20)
(C++20)
(C++20)
(C++20)
(C++20)
(C++20)
(until C++17*)
(until C++17*)
(until C++17*)
(until C++17*)
(until C++17*)  
(until C++17*)
(until C++17*)(until C++17*)(until C++17*)(until C++17*)
(until C++20*)
(until C++20*)
(until C++17*)(until C++17*)
(until C++17*)(until C++17*)
(until C++17*)
(until C++17*)(until C++17*)(until C++17*)(until C++17*)
(until C++20*)
(until C++20*)
Defined in header 
 
 
<type_traits> 
 Defined in header 
 
 
<functional> 
 template< class T >
struct unwrap_reference;
 (1) 
 (since C++20) 
struct unwrap_reference;
template< class T >
struct unwrap_ref_decay;
 (2) 
 (since C++20) 
struct unwrap_ref_decay;
Unwraps any std::reference_wrapper : changing std::reference_wrapper <U> to U&.
2) If the decayed 
T is a specialization of std::reference_wrapper , unwraps it; otherwise, T is decayed.If the program adds specializations for any of the templates described on this page, the behavior is undefined.
[edit] Nested types
 Type
 Definition
type
 
(1) U& if T is std::reference_wrapper <U>; T otherwise
(2) U& if std::decay_t <T> is std::reference_wrapper <U>; std::decay_t <T> otherwise
[edit] Helper types
template<class T>
using unwrap_reference_t = unwrap_reference<T>::type;
 (1) 
 (since C++20) 
using unwrap_reference_t = unwrap_reference<T>::type;
template<class T>
using unwrap_ref_decay_t = unwrap_ref_decay<T>::type;
 (2) 
 (since C++20) 
using unwrap_ref_decay_t = unwrap_ref_decay<T>::type;
[edit] Possible implementation
template<class T> struct unwrap_reference { using type = T; }; template<class U> struct unwrap_reference<std::reference_wrapper <U>> { using type = U&; }; template<class T> struct unwrap_ref_decay : std::unwrap_reference<std::decay_t <T>> {};
[edit] Notes
std::unwrap_ref_decay performs the same transformation as used by std::make_pair  and std::make_tuple .
| Feature-test macro | Value | Std | Feature | 
|---|---|---|---|
| __cpp_lib_unwrap_ref | 201811L | (C++20) | std::unwrap_ref_decayandstd::unwrap_reference | 
[edit] Example
Run this code
#include <cassert> #include <functional> #include <iostream> #include <type_traits> int main() { static_assert(std::is_same_v <std::unwrap_reference_t<int>, int>); static_assert(std::is_same_v <std::unwrap_reference_t<const int>, const int>); static_assert(std::is_same_v <std::unwrap_reference_t<int&>, int&>); static_assert(std::is_same_v <std::unwrap_reference_t<int&&>, int&&>); static_assert(std::is_same_v <std::unwrap_reference_t<int*>, int*>); { using T = std::reference_wrapper <int>; using X = std::unwrap_reference_t<T>; static_assert(std::is_same_v <X, int&>); } { using T = std::reference_wrapper <int&>; using X = std::unwrap_reference_t<T>; static_assert(std::is_same_v <X, int&>); } static_assert(std::is_same_v <std::unwrap_ref_decay_t<int>, int>); static_assert(std::is_same_v <std::unwrap_ref_decay_t<const int>, int>); static_assert(std::is_same_v <std::unwrap_ref_decay_t<const int&>, int>); { using T = std::reference_wrapper <int&&>; using X = std::unwrap_ref_decay_t<T>; static_assert(std::is_same_v <X, int&>); } { auto reset = []<typename T>(T&& z) { // x = 0; // Error: does not work if T is reference_wrapper<> // converts T&& into T& for ordinary types // converts T&& into U& for reference_wrapper<U> decltype(auto) r = std::unwrap_reference_t<T>(z); std::cout << "r: " << r << '\n'; r = 0; // OK, r has reference type }; int x = 1; reset(x); assert (x == 0); int y = 2; reset(std::ref (y)); assert (y == 0); } }
Output:
r: 1 r: 2