转发引用总是被推断为某种引用吗?



我认为转发引用是完美转发的一部分。我试着向别人解释它,却意识到我不知道:它能把T&&推断为某种非参考类型吗?

#include <type_traits>
#include <utility>
template <typename Expected>
void checkDeduction(auto&& x) {
static_assert(std::is_same_v<Expected, decltype(x)>);
}
int main() {
checkDeduction<int&&>(1);
const volatile int x = 0;
checkDeduction<const volatile int&>(x);
checkDeduction<const volatile int&&>(std::move(x)); // Weird, but whatever.   
// Is there anything for which checkDeduction<int>(foo) will compile?
}

https://godbolt.org/z/cr8K1dsKa

我认为答案是"不",它总是一个右值引用或左值引用。

我认为这是因为如果f转发到g:

decltype(auto) f(auto&& x) { return g(std::forward<decltype(x)>(x)); }

不是fg具有相同的签名,而是f是用f的调用者提供的值类别编译的,所以如果gint,而你调用f(1),那么f得到int&&并将其转发给g。在调用g时,int&&衰变成int

显然T&&是某种引用;有趣的问题是T是否总是被推断为引用类型。答案是:如果参数是类型为U的左值,则T将是U&;如果参数是类型为右值,则T将只是U

这里有一种错失的机会:语言可能会说prvalue推导为Uxvalue被推断为U&&(它仍然会被"外部"引用操作符崩溃)。然而,判断是,这种区别并不重要,至少不足以证明在任何地方创建额外的模板专门化是合理的。

仍然可以写f<X&&>(…)转发引用的模板形参是一个右值引用,尽管这通常不会完成任何事情。

最新更新