I think about forwarding references as part of perfect forwarding. I was trying to explain it to someone and realized I didn't know: Can it ever deduce T&&
as some non-reference type?
#include <type_traits>
#include <utility>
template <typename Expected>
void checkDeduction(auto&& x) {
static_assert(std::is_same_v<Expected, decltype(x)>);
}
int main() {
checkDeduction<int&&>(1);
const volatile int x = 0;
checkDeduction<const volatile int&>(x);
checkDeduction<const volatile int&&>(std::move(x)); // Weird, but whatever.
// Is there anything for which checkDeduction<int>(foo) will compile?
}
https://godbolt.org/z/cr8K1dsKa
I think the answer is "no", that it's always either an rvalue or lvalue reference.
I think this is because if f
forwards to g
:
decltype(auto) f(auto&& x) { return g(std::forward<decltype(x)>(x)); }
it's not that f
has the same signature as g
, but rather that f
is compiled with the value categories that the caller of f
provides, so if g
takes int
, and you call f(1)
then f
gets an int&&
and forwards that to g
. At that call to g
, the int&&
decays to an int
.