Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
178 views
in Technique[技术] by (71.8m points)

c++ - Is there a reason declval returns add_rvalue_reference instead of add_lvalue_reference

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...