参考折叠规则未按预期应用?

Reference collapsing rules not applying as expected?

我正在刷新我对 C++ 中完美转发如何工作的记忆。我意识到对 std::forward 的调用被迫提供显式模板参数是有原因的(即在处理实际上是左值的右值引用时),但是在对实际代码进行健全性检查时,我对此感到惊讶(有点相关)场景:

#include <iostream>
#include <utility>
#include <type_traits>

template<class T>
T&& fwd(T& t) {
    return static_cast<T&&>(t);
}

template<class T>
T&& fwd(T&& t) {
    return static_cast<T&&>(t);
}

int main()
{
    int lnum = 3;
    if (std::is_rvalue_reference<decltype(fwd(lnum))>::value)
        std::cout << "It's rref." << std::endl;           // this get's printed on screen 
    else
        std::cout << "It's lref." << std::endl;

    return 0;
}

如果我正确理解引用折叠(我相信我理解),类型推导应该是这样的:

int& && fwd(int& & t) {                        
    return static_cast<int& &&>(t);         
}

导致

int& fwd(int& t) {                        
    return static_cast<int&>(t);         
}

显然不是这样。我在这里错过了什么?

首先调用的函数是T&& fwd(T& t)。因此,没有转发参考参数。参数是左值引用,推导的 Tint。因此,没有对 collapse 的引用,静态转换会产生 int&&.

如果调用的函数是 T&& fwd(T&& t)(即如果不存在更好的匹配重载),那么您对引用折叠的解释是正确的(除了参数 int& && 也折叠 int&) 并且 return 类型确实是左值引用。

实际上,没有发生引用崩溃。需要注意的相关功能模板,即选中的是:

template<class T>
T&& fwd(T& t) { // <-- not a forwarding reference
    return static_cast<T&&>(t);
}

注意这个函数模板有没有 转发引用 – 函数参数t只是一个左值引用 (T& t).

T模板参数推导为int——不是int&——因为t不是转发引用但只是一个左值引用。如果你只是将上面的函数模板中的T替换为int,那么你将得到:

template<class T>
int&& fwd(int& t) {
    return static_cast<int&&>(t);
}

不应用引用折叠,因为这里没有这样的东西,否则最终会成为对引用的引用(例如,int& &&int&& &&).