With add_rvalue_reference
:
declval<Foo>()
is of type Foo&&
.
declval<Foo&>()
is of type Foo&
(reference collapsing: “Foo& &&
” collapses to Foo&
).
declval<Foo&&>()
is of type Foo&&
(reference collapsing: “Foo&& &&
” collapses to Foo&&
).
With add_lvalue_reference
:
declval<Foo>()
would be of type Foo&
.
declval<Foo&>()
would be of type Foo&
(reference collapsing: “Foo& &
” collapses to Foo&
).
declval<Foo&&>()
would be of type Foo&
(!) (reference collapsing: “Foo&& &
” collapses to Foo&
).
that is, you would never get a Foo&&
.
Also, the fact that declval<Foo>()
is of type Foo&&
is fine (you can write Foo&& rr = Foo();
but not Foo& lr = Foo();
). And that declval<Foo&&>()
would be of type Foo&
just feels “wrong”!
Edit: Since you asked for an example:
#include <utility>
using namespace std;
struct A {};
struct B {};
struct C {};
class Foo {
public:
Foo(int) { } // (not default-constructible)
A onLvalue() & { return A{}; }
B onRvalue() && { return B{}; }
C onWhatever() { return C{}; }
};
decltype( declval<Foo& >().onLvalue() ) a;
decltype( declval<Foo&&>().onRvalue() ) b;
decltype( declval<Foo >().onWhatever() ) c;
If declval
used add_lvalue_reference
you couldn't use onRvalue()
with it (second decltype
).
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…