#include <typeinfo>
#include <iostream>
template <typename T>
void f_ref(T &arg) {
std::cout << typeid(arg).name() << std::endl;
}
template <typename T>
void f_pointer(T *arg) {
std::cout << typeid(arg).name() << std::endl;
}
template <typename T>
void f_refref(T &&arg) {
std::cout << typeid(arg).name() << std::endl;
}
template <typename T>
void f_val(T arg) {
std::cout << typeid(arg).name() << std::endl;
}
int main() {
int a = 10;
const int ca = a;
const int &ra = a;
f_ref(a); // int &
f_ref(ca); // const int &
f_ref(ra); // const int &

const int *pa = &a;
f_pointer(&a);
f_pointer(pa);

f_refref(a); // int &
f_refref(ca); // const int &
f_refref(ra); // const int &
f_refref(27); // &&

f_val(a); // int
f_val(ca); // int
f_val(ra); // int

return 0;
}

1.在模板参数推导中,具有引用类型的实参会被剥掉&,如上例的f_ref;

2.在模板参数推导中,如果参数是右值引用(&&),实参如果有具体的地址(已生成对象)会被特殊处理,即非引用类型会加上引用,如上例的f_refref(a),引用类型不变,如上例的f_refref(ca),实参如果是右值(未分配具体地址),则参数会以move方式传递,如果上例f_refref(27);

3.在模板参数推导中,实参传递会剥掉引用,产生新的临时对象,如果上例的f_val(ca)和f_val(ra)。