Is it ever possible for this code to print "neither"?
using namespace std;
template<typename T>
void foo(T&& t) {
if constexpr (is_lvalue_reference_v<T>) {
cout << "lv" << endl;
} else if constexpr (is_rvalue_reference_v<T>) {
cout << "rv" << endl;
} else {
cout <<"neither" << endl;
}
}
Is it ever possible for this code to print "neither"?
Yes, "neither" will be printed any time an rvalue is passed to foo
and no explicit template parameter is given:
foo(42); // "neither" is printed because T is deduced as int
Or when a non-reference type is explicitly specified:
int i=0;
// "neither" is printed because T is explicitly specified as int:
foo<int>(std::move(i));
While T
can be a non-reference type, the type of t
will always be a reference type. There are three possibilities for the type of t
:
T
is a value type (i.e. int
): the type of t
is int&&
; rvalue-reference to int
.T
is an lvalue-reference (i.e. int&
): the type of t
is int& &&
, which collapses to int&
; lvalue-reference to int
.T
is an rvalue-reference (i.e. int&&
): the type of t
is int&& &&
, which collapses to int&&
; rvalue-reference to int
.This is the mechanism by which forwarding references work. If you pass an rvalue to foo
, then T
will be deduced to be a value type. If you pass an lvalue then T
will be deduced to be an lvalue-reference type.