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 names T&; otherwise, type names T. [ 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>); };

Tags:

C++