What is the purpose of std::add_lvalue_reference and std::add_rvalue_reference?
void&
is ill-formed. std::add_lvalue_reference<void>
is void
.
In general, add_lvalue_reference
does not add reference to types if it is not possible. Per [meta.trans.ref]:
template <class T> struct add_lvalue_reference;
If T names a referenceable type then the member typedef
type
namesT&
; otherwise,type
namesT
. [ Note: This rule reflects the semantics of reference collapsing ([dcl.ref]). — end note ]
What is a referenceable type? Per [defns.referenceable], a referenceable type is
an object type, a function type that does not have cv-qualifiers or a ref-qualifier, or a reference type [ Note: The term describes a type to which a reference can be created, including reference types. — end note ]
They're not the same in all cases. The effects of std::add_lvalue_reference
, std::add_rvalue_reference
are,
1) If T is an object type or a function type that has no cv- or ref- qualifier, provides a member typedef type which is T&. If T is an rvalue reference to some type U, then type is U&. Otherwise, type is T.
2) If T is an object type or a function type that has no cv- or ref- qualifier, provides a member typedef type which is T&&, otherwise type is T.
e.g. the result would be defferent for funciton type has cv- or ref-qualifier. The following code fails,
{ using T = void() const; static_assert(std::is_same_v<std::add_lvalue_reference_t<T>, T &>); };
The result of std::add_lvalue_reference
is just T
here.
{ using T = void() const; static_assert(std::is_same_v<std::add_lvalue_reference_t<T>, T>); };