std::unwrap...ap_ref_decay(3)
π std::unwrap_reference & std::unwrap_ref_decay π
okay bestie, quick vibe check: this is the C++ Standard Libary manual page std::unwrap...ap_ref_decay(3), and the actual stars of the show are std::unwrap_reference and std::unwrap_ref_decay. Both are (since C++20) type traits, and they're here to unwrap std::reference_wrapper when you need the underlying reference type. slay. β¨
πΈ NAME πΈ
std::unwrap_reference,std::unwrap_ref_decay β and yep, the NAME line repeats std::unwrap_reference,std::unwrap_ref_decay after the dash, because that's the page's whole name. π
π¦ Synopsis π¦
Headers first, bestie β both of these are in the mix:
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;
- If
Tisstd::reference_wrapper<U>for some typeU, this provides a member type aliastypethat namesU&; otherwise, it provides a member type aliastypethat namesT. π«Ά - If
Tisstd::reference_wrapper<U>for some typeU, ignoring cv-qualification and referenceness, this provides a member type aliastypethat namesU&; otherwise, it provides a member type aliastypethat namesstd::decay_t<T>. π₯
π¨ If the program adds specializations for any of the templates described on this page, the behavior is undefined. Not cute, not allowed, undefined behavior era. π
π Member types π
- Name:
type- (1)
U&ifTisstd::reference_wrapper<U>;Totherwise - (2)
U&ifstd::decay_t<T>isstd::reference_wrapper<U>;std::decay_t<T>otherwise
- (1)
β¨ Helper types β¨
These helper aliases are the glow-up shortcuts:
template<class T> (1) (since C++20)
using unwrap_reference_t = unwrap_reference<T>::type;
template<class T> (2) (since C++20)
using unwrap_ref_decay_t = unwrap_ref_decay<T>::type;
π Possible implementation π
no cap, here's the possible implementation in all its tiny template glory:
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. iconic behavior, honestly. π
Feature-test macro vibes:
__cpp_lib_unwrap_refβ value201811Lβ standard(C++20)β feature:std::unwrap_ref_decayandstd::unwrap_reference
π 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
π« 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)
made with π by your local type-trait-obsessed bestie Β· source/version: http://cppreference.com Β· date: 2024.06.10 Β· page: std::unwrap...ap_ref_decay(3) π«Ά
π¦ where this page comes from
- nixpkgs unstable: stdman 2024.07.05
- opensuse-leap 16.0: stdman 2024.07.05-bp160.1.9 Β· MIT
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms