2

I've just read this in C++ Primer :

A function parameter that is an rvalue reference to a template type parameter (i.e., T&&) preserves the constness and lvalue/rvalue property of its corresponding argument.

But I don't understand why T&& parameters have this feature while T&'s haven't.

What's the C++ logic behind this ?

DigitalRomance
  • 305
  • 2
  • 7
  • 1
    I feel like this sentence is wrong, a `T&&` when `T` is a deduced template argument isn't a rvalue reference, its a universal reference. – tkausl Jul 15 '22 at 22:33
  • This reads like a misprint that refers to not function parameters but template parameters. That's an entire different ballgame, and `T &&` is "special sauce" as far as template parameters go. Can you clarify and provide more context of this quote from this book. – Sam Varshavchik Jul 15 '22 at 22:42
  • @tkausl they are formally known as "forwarding references" in the standard, not "universal references". See [Is there a difference between universal references and forwarding references?](https://stackoverflow.com/questions/39552272/) – Remy Lebeau Jul 15 '22 at 23:55

1 Answers1

1

Because if T is a function template argument, then T& is a non-constant reference to T while T&& is called a forwarding reference if used as type for a function argument. Other T&&, e.g. in template<typename T> void foo(std::vector<T&&> x) is really an r-value reference that cannot deduce const (not that const r-value references are very useful).

Since we want to automatically differentiate between the following cases:

  • const int x = 5; foo(x);
  • int x = 5; foo(std::move(x));
  • int x = 5; foo(x);
  • foo(int{5});

while retaining a single template<typename T> foo(T&& x) definition, forwarding references were given the ability to deduce const.

As to why T& cannot deduce const, it likely never was the intent of this feature. It really meant to serve as a non-constant reference to a generic type. It would make x.non_const_member() fail to compile sometimes.

Yes, that happens for T&& too but the intent here is exactly about forwarding the type as it was passed to us to somewhere else, not necessarily modifying the object ourselves.

Quimby
  • 17,735
  • 4
  • 35
  • 55