std::add_lv...ue_reference(3)
bestie, welcome to the C++ Standard Libary manual, section 3 ππ
β this page is std::add_lv...ue_reference(3), and it's all about the type-trait twins std::add_lvalue_reference and std::add_rvalue_reference. No cap, they're lowkey iconic.
β¨ NAME β¨
std::add_lvalue_reference,std::add_rvalue_referenceβ the two type traits this page covers. The original NAME line is literally that pair, no extra lore π
π¦ Synopsis π¦
Defined in header <type_traits>.
template< class T > (1) (since C++11)
struct add_lvalue_reference;
template< class T > (2) (since C++11)
struct add_rvalue_reference;
Creates an lvalue or rvalue reference type of T. Periodt.
Here's the vibe check on what the nested type ends up being:
- Type trait (1) β if
Tis a referenceable type, the nestedtypeisT&^[1]; ifTis not a referenceable type, it'sT. - Type trait (2) β if
Tis a referenceable type, the nestedtypeisT&&^[2]; ifTis not a referenceable type, it'sT.
^[1] This rule reflects the semantics of reference collapsing.
^[2] This rule reflects the semantics of reference collapsing. Note that std::add_rvalue_reference<T&>::type is T&, which is not an rvalue reference type.
If the program adds specializations for any of the templates described on this page, the behavior is undefined. π So don't do that, bestie.
π Helper types π
template< class T >
using add_lvalue_reference_t = typename add_lvalue_reference<T>::type;
(since C++14)
template< class T >
using add_rvalue_reference_t = typename add_rvalue_reference<T>::type;
(since C++14)
πΈ Notes πΈ
The major difference to directly using T& or T&& is that T can be a non-referenceable type. For example, std::add_lvalue_reference<void>::type is void, while void& leads to a compilation error. Not me finding that out the hard way ππ
π§ Possible implementation π§
namespace detail
{
template<class T>
struct type_identity { using type = T; }; // or use std::type_identity (since C++20)
template<class T> // Note that βcv void&β is a substitution failure
auto try_add_lvalue_reference(int) -> type_identity<T&>;
template<class T> // Handle T = cv void case
auto try_add_lvalue_reference(...) -> type_identity<T>;
template<class T>
auto try_add_rvalue_reference(int) -> type_identity<T&&>;
template<class T>
auto try_add_rvalue_reference(...) -> type_identity<T>;
} // namespace detail
template<class T>
struct add_lvalue_reference
: decltype(detail::try_add_lvalue_reference<T>(0)) {};
template<class T>
struct add_rvalue_reference
: decltype(detail::try_add_rvalue_reference<T>(0)) {};
π¦ Example π¦
Run this code, bestie:
#include <type_traits>
using non_ref = int;
static_assert(std::is_lvalue_reference_v<non_ref> == false);
using l_ref = std::add_lvalue_reference_t<non_ref>;
static_assert(std::is_lvalue_reference_v<l_ref> == true);
using r_ref = std::add_rvalue_reference_t<non_ref>;
static_assert(std::is_rvalue_reference_v<r_ref> == true);
using void_ref = std::add_lvalue_reference_t<void>;
static_assert(std::is_reference_v<void_ref> == false);
int main() {}
π§ Defect reports π§
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
- DR
LWG 2101β applied to C++11. Behavior as published: the program was ill-formed ifTis a function type with cv or ref. Correct behavior: the type produced isTin this case.
β See also β
is_reference(C++11) β checks if a type is either an lvalue reference or rvalue reference (class template)remove_reference(C++11) β removes a reference from the given type (class template)remove_cvref(C++20) β combinesstd::remove_cvandstd::remove_reference(class template)
source: http://cppreference.com Β· version/date: 2024.06.10 Β· page: std::add_lv...ue_reference(3) πβ¨ That's the whole manual page, bestie β go forth and reference responsibly π«Ά
π¦ 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