Scroll to navigation

std::unwrap_reference,std::unwrap_ref_decay(3) C++ Standard Libary std::unwrap_reference,std::unwrap_ref_decay(3)

NAME

std::unwrap_reference,std::unwrap_ref_decay - std::unwrap_reference,std::unwrap_ref_decay

Synopsis


Defined in header <type_traits>
Defined in header <functional>
template< class T > (1) (since C++20)
struct unwrap_reference;
template< class T > (2) (since C++20)
struct unwrap_ref_decay;


1) If T is std::reference_wrapper<U> for some type U, provides a member typedef type
that names U&; otherwise, provides a member typedef type that names T.
2) If T is std::reference_wrapper<U> for some type U, ignoring cv-qualification and
referenceness, provides a member typedef type that names U&; otherwise, provides a
member typedef type that names std::decay_t<T>.


The behavior of a program that adds specializations for any of the templates
described on this page is undefined.

Member types


Name Definition
1) U& if T is std::reference_wrapper<U>; T otherwise
type
2) U& if std::decay_t<T> is std::reference_wrapper<U>; std::decay_t<T>
otherwise

Helper types


template<class T> (1) (since C++20)
using unwrap_reference_t = typename unwrap_reference<T>::type;
template<class T> (2) (since C++20)
using unwrap_ref_decay_t = typename unwrap_ref_decay<T>::type;

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>> {};

Notes


std::unwrap_ref_decay performs the same transformation as used by std::make_pair and
std::make_tuple.


Feature-test macro: __cpp_lib_unwrap_ref

Example

// Run this code


#include <cassert>
#include <iostream>
#include <functional>
#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

See also


reference_wrapper CopyConstructible and CopyAssignable reference wrapper
(C++11) (class template)
make_pair creates a pair object of type, defined by the argument types
(function template)
make_tuple creates a tuple object of the type defined by the argument types
(C++11) (function template)

2022.07.31 http://cppreference.com