§20.2.4 [declval]
template <class T>
typename add_rvalue_reference<T>::type declval() noexcept; // as unevaluated operand
Why use add_rvalue_reference here?
From §20.9.7.2 [meta.trans.ref] on add_rvalue_reference:
If
Tnames an object or function type then the member typedeftypeshall nameT&&; otherwise,typeshall nameT. [ Note: This rule reflects the semantics of reference collapsing (8.3.2). For example, when a typeTnames a typeT1&, the typeadd_rvalue_reference<T>::typeis not an rvalue reference. —end note ]
Since add_rvalue_reference is meant to reflect reference collapsing anyways, why not just use T&& like the following?
template<class T>
T&& declval();
What could go wrong? What exactly are the differences between the two versions?
I don’t know if this is the actual reason, but
add_rvalue_referencehas different behavior forvoid.add_rvalue_reference<void>::typeis simplyvoid.void&&is an error.