引用折疊
在現代 C++ 中一共有兩種引用類型,左值引用與右值引用,因此,在類型組合與推導的時候它們可能會出現四種組合。但是 C++ 不允許出現引用的引用,因此,需要一種機制來消除多重引用,這個機制就是引用折疊,引用折疊規則如下:

補充幾點:
- 引用折疊是針對通用引用的
- 當左值作為參數傳入的時候模板參數 T 推導為左值引用類型 T&
- 當右值作為參數傳入的時候模板參數 T 推導為值類型 T
- 然后再應用引用折疊規則,推導出具體的參數類型
引用折疊使用場景
引用折疊發生的場景不多,主要有下面四種情形:
- T&& 模板類型推導
- auto&& 變量類型推導,包括 Lambda 形參
- typedef / using T&& 別名聲明
- decltype(T)
代碼示例 :
#include
class X {};
template void func(T &?m) {
if constexpr (std::is_lvalue_reference_v) {
std::cout << "T is lvalue reference\n";
} else {
std::cout << "T is non-reference\n";
}
}
template class Y {
public:
typedef T &&rvalueRef_t0;
using rvalueRef_t1 = T &&;
rvalueRef_t1 y_;
};
int main() {
std::cout << std::boolalpha;
using std::cout, std::is_same_v;
X x1{};
func(x1);
func(std::move(x1));
X x20{};
auto &&x21 = x20;
cout << is_same_v << '\n';
auto &&x22 = std::move(x20);
cout << is_same_v << '\n';
cout << is_same_v::rvalueRef_t0> << '\n';
cout << is_same_v::rvalueRef_t1> << '\n';
cout << is_same_v::rvalueRef_t0> << '\n';
cout << is_same_v::rvalueRef_t1> << '\n';
cout << is_same_v::y_)> << '\n';
return 0;
}
再談 std::forward
圖解 std::forward 與引用折疊的工作過程:

std::forward 對于左值,返回左值引用,對于右值,返回右值引用,保留類型修飾符
總結
- 理解引用折疊規則
- 了解引用折疊發生的場景
- 理解完美轉發的本質,以及引用折疊規則的應用
|