通用引用(universal reference) 是用来特指一种引用的类型。构成通用引用有两个条件:
-
必须满足
T&&这种形式 -
类型
T必须是通过推断得到的
下面看一个例子:
template <typename T>
class A {
void func(T&& t) {}
}
上面的例子中func 函数的T&& 并不是通用引用。因为在类定义变量时,类型T就已经确定了,并不需要进行推断。如:A<int> a;
哪些情况下是通用引用呢:
-
函数模板参数:
#include <iostream> #include <type_traits> template <typename T> void print_reference_type(T &&i) { if (std::is_lvalue_reference<decltype(i)>::value) { std::cout << "lvalue: " << i << std::endl; } else if (std::is_rvalue_reference<decltype(i)>::value) { std::cout << "rvalue: " << i << std::endl; } else { std::cout << "unknown value: " << i << std::endl; } } int main(void) { int i = 0; print_reference_type(i); // lvalue: 0 print_reference_type(1); // rvalue: 1 }
-
auto声明:#include <iostream> #include <type_traits> void print_reference_type(auto &&i) { if (std::is_lvalue_reference<decltype(i)>::value) { std::cout << "lvalue: " << i << std::endl; } else if (std::is_rvalue_reference<decltype(i)>::value) { std::cout << "rvalue: " << i << std::endl; } else { std::cout << "unknown value: " << i << std::endl; } } int main(void) { int i = 0; print_reference_type(i); // lvalue: 0 print_reference_type(1); // rvalue: 1 }
那通用引用与其他引用有什么区别呢?最重要的区别是引用类型合成(Reference Collapsing Rules)。规则很简单:
T& & => T&T&& & => T&T& && => T&T&& && => T&&
简单来说,就是传进来的如果是左值引用那就是左值引用,如果是右值引用那就是右值引用。