Is there a reason declval returns add_rvalue_reference instead of add_lvalue_reference

c++, c++11, declval, language-lawyer, reference-collapsing

Solution

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`).

Problem

changing a type into a `reference` to a type, allows one to access the members of the type without creating an instance of the type. This seems to be true for both `lvalue references` and `rvalue references`. `declval` is implemented with `add_rvalue_reference` instead of `add_lvalue_reference`, - is this just a convention, - or are there examples of use where `add_rvalue_reference` is preferable? Edit: I suppose I was slightly vague, these answers are all very good but touch on slightly different points. There are two different answers to use proposed, Howard emphasized that you can choose which reference your type has, making `add_rvalue_reference` more flexible. The other answers emphasize that the default behavior automatically chooses references which reflect the input type more naturally. I don't know what to pick! If somebody could add two simple examples, motivating the need for each property respectively, then I'll be satisfied.

Original source