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.
Is it ever possible for this code to print "neither"?
Yes.
foo(5); // neither
If I accept a parameter via universal reference, is exactly one of is_rvalue_reference and is_lvalue_reference true?
The parameter t will either have rvalue reference type or lvalue reference type. The type T on the other hand will be different depending on deduction and reference collapsing rules. If instead you change is_lvalue/rvalue_reference<T> to is_lvalue/rvalue_reference<decltype(t)> then the else path can never be executed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With