完美转发中的模板参数推导

问题描述 投票:0回答:1

我正在学习完美转发,并运行示例代码(如下所示)

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&&

我找不到讨论这个的文章

c++ c++11 template-argument-deduction perfect-forwarding reference-collapsing
1个回答
0
投票

当您将参数传递给具有 转发引用

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&&
折叠后的内容。

© www.soinside.com 2019 - 2024. All rights reserved.