Forwarding reference does not deduce to rvalue reference

61 Views Asked by At

First, this question has been asked by others, see this and this, but (I think) neither of them provides a satisfactory answer.

According to cppreference,

Before deduction begins, the following adjustments to P and A are made:

  1. If P is not a reference type, a) if A is an array type, A is replaced by the pointer type obtained from array-to-pointer conversion; b) otherwise, if A is a function type, A is replaced by the pointer type obtained from function-to-pointer conversion; c) otherwise, if A is a cv-qualified type, the top-level cv-qualifiers are ignored for deduction:
  2. If P is a cv-qualified type, the top-level cv-qualifiers are ignored for deduction.
  3. If P is a reference type, the referenced type is used for deduction.
  4. If P is an rvalue reference to a cv-unqualified template parameter (so-called forwarding reference), and the corresponding function call argument is an lvalue, the type lvalue reference to A is used in place of A for deduction

After these transformations, the deduction processes as described below (cf. section Deduction from a type) and attempts to find such template arguments that would make the deduced A (that is, P after adjustments listed above and the substitution of the deduced template parameters) identical to the transformed A, that is A after the adjustments listed above.

Using this rule, we look at the following code, with type_name from this answer:

template<typename T>
void foo(T && t) {
    std::cout << type_name<T>();
}

int main() {
    int a = 1;
    foo(std::move(a)); // int, not int&&
}

From rule 3, since P = T && is a reference type, the referenced type T is used for deduction, i.e. deduced A is T.

A is the type of std::move(a), which is a rvalue of type int &&. No transformation is applicable, so transformed A is int &&.

To make deduced A identical to transformed A, we shall have T = int &&.

But the code above shows T = int. Is this an inaccuracy of cppreference, or my misunderstanding?

1

There are 1 best solutions below

0
HolyBlackCat On BEST ANSWER

Expressions can't have reference types, so the type of std::move(a) is int, not int &&.