I want to create a function that correctly recognizes the type of its parameter.
template<class T> void test(T&& t){
if constexpr(std::is_same_v<T,int>){
std::cout<< "= int"<<std::endl;
}
if constexpr(std::is_same_v<T,const int&>){
std::cout<< "= const int&"<<std::endl;
}
if constexpr(std::is_same_v<T,int&>){
std::cout<< "= int&"<<std::endl;
}
if constexpr(std::is_same_v<T,int&&>){
std::cout<< "= int&&"<<std::endl;
}
if constexpr(std::is_same_v<T,std::nullptr_t>){
std::cout<< "= std::nullptr_t"<<std::endl;
}
}
int funcReturnInt(){return 5;}
int main(){
const int a=0;
test(funcReturnInt()); // int (correct)
test(a); // const int& (correct)
test(nullptr); // std::nullptr_t (correct)
int s=0;
test(std::move(s)); // print "int" (not "int&&") , I am sad
}
How to create the test() function so it can recognize the type of its single parameter correctly in every case?
I am new to T&&, so I have read some guides about rvalue references (1, 2, 3), but they don't describe how to create such a full-awareness wildcard function like test<T>(T??).
I will apply the solution as test() requires ... {} later.
I prefer to avoid overloading, because I love to make the code compact in 1 place (for educational purpose, too).
Edit :: Very useful comments state that it is generally not possible. Why does my code check other cases correctly, but C++ takes a liberty to get rid of my &&? Please post it as a solution.
I still doubt why int& in main() becomes T=int& correctly but int&& in main() becomes T=int.
Emphasis mine:
In this declaration:
whilst commonly mistaken for one,
tis not an rvalue reference, it is forwarding reference (sometimes referred to as universal references). To understand forwarding references we need to understand more than rvalue references, e.g. reference collapsing rules and perfect forwarding. See e.g. the following Q&A for details:In the call
the argument type A is
int&&, the complete parameter type isint&&meaning the deducedTisintRefer to e.g. [temp.deduct.call]/3 for details.
Universal references particularly apply reference collapsing rules when the argument type is an lvalue. For the call
test(a)the argument type isint const, but for purposes of deduction,int const&is used in place, deducingTtoint const&, where the resulting function parameter typeT&&is collapsed fromint const& &&toint const&(&& &->&).