我正在学习完美转发,并运行示例代码(如下所示)
template<typename T>
void show_type(T t){
std::cout << typeid(t).name() << std::endl;
}
template<typename T>
void perfect_forwarding(T &&t){
std::cout << std::boolalpha << "is std::string: " << std::is_same<std::string, T>::value << std::endl;
std::cout << std::boolalpha << "is lval-reference: " << std::is_lvalue_reference<T>::value << std::endl;
std::cout << std::boolalpha << "is rval-reference: " << std::is_rvalue_reference<T>::value << std::endl;
show_type(static_cast<T&&>(t));
}
std::string get_string(){
return "hi world";
}
int main() {
std::string s = "hello world";
perfect_forwarding(s); //call 1
perfect_forwarding(get_string()); //call 2
}
输出是
is std::string: false
is lval-reference: true
is rval-reference: false
Ss
is std::string: true
is lval-reference: false
is rval-reference: false
Ss
我用gdb调试,找出对perfect_forwarding()的两次调用 被实例化为
perfect_forwarding<std::string&>(std::string&) //for call 1
perfect_forwarding<std::string>(std::string&&) //for call 2
我的问题是
在
call 1
中,为什么T被扣除为std::string&,我以为会是std::string,而T&&应该被扣除为std::string&&
在
call 2
中,我认为T应该被扣除为std::string&&
我找不到讨论这个的文章
当您将参数传递给具有 转发引用
T&&
作为该参数的参数的函数时,会发生以下两种情况之一:
如果参数是左值(例如
s
),则 T
推导出左值引用(例如 std::string&
)。
没有对引用的引用,所以你会得到引用崩溃。
例如, T&&
,其中 T = std::string&
似乎是对左值引用的右值引用,并且这会折叠为 std::string&
。
否则,如果参数是右值(例如
get_string()
),则 T
会推导出表达式的类型 (std::string
),因此 T&&
就是 std::string&&
。
请注意,在您的 GDB 检查中
perfect_forwarding<std::string&>(std::string&)
perfect_forwarding<std::string>(std::string&&)
...尖括号之间出现的是
T
推导出来的,
括号之间出现的是 T&&
折叠后的内容。