转发非引用类型的引用

Forwarding references for non-reference types

本文关键字:引用 引用类型 转发      更新时间:2023-10-16
template<typename T>
void F(T&& x) {}

如果我们用 int 类型的参数调用它,一切都很清楚 - 引用崩溃发生,我们仍然有左值引用。但是,如果我们用例如 int 参数来调用它会发生什么。我的想法:我们已经推导出了类型T=int,用右值引用装饰它,所以F采用int&&argument,用int类型调用它会导致错误。但在现实中,F将这样的论点作为左值引用。左值引用从何而来?编译器应用了哪些规则来从 int 获取 int&?

自 C++17 年以来,C++标准中就有了转发引用的概念。通常,模板参数被推断为非引用。但是对于转发引用的特定情况,如果相应的参数是左值,则该参数被推导为引用。C++标准 (N4700)[温度超过.扣除调用]/3:

[...]转发引用是对 cv 非限定模板参数的右值引用,该参数不表示类模板的模板参数(在类模板参数推导期间 ([over.match.class.deduct]))。如果 P 是转发引用,参数是左值,则使用类型"对 A 的左值引用"代替 A 进行类型推断。[...]

对于函数调用的问题,它与 C++11(N337) 和 C++14(N414) [temp.over.deduct.call]/3 中的等效段落具有相同的含义:

[...]如果 P 是对 cv 非限定模板参数的右值引用,并且参数是左值,则使用类型"对 A 的左值引用"代替 A 进行类型推导[...]

转发引用推导出左值的左值引用和右值的右值引用。例如,即使对于int&&类型的左值,它仍然会推导出int&(就像对于int类型的左值一样),同样,对于intint&&类型的右值,它将推导出int&&

template<typename T>
class show;
template<typename T>
void F(T&& x) 
{ show<decltype(x)>();}
int main() {
int&& x = 5;
F(x);
}
main.cpp:6:3: error: implicit instantiation of undefined template 'show<int &>'
int main() {
F(5);
}
main.cpp:6:3: error: implicit instantiation of undefined template 'show<int &&>'
int main() {
int x = 5;
F(x);
}
main.cpp:6:3: error: implicit instantiation of undefined template 'show<int &>'
int main() {
F([]()->int{return 5;}());
}
main.cpp:6:3: error: implicit instantiation of undefined template 'show<int &&>'