std :: forward如何推导_Ty的类型?

时间:2019-05-29 21:13:16

标签: c++ std perfect-forwarding

我正在学习模板,尤其是std::forward;当我检查其实现时,它在其参数列表中使用了另一个类模板std::remove_reference

template<class _Ty>
_Ty&& forward(typename remove_reference<_Ty>::type& _Arg)
{// forward an lvalue as either an lvalue or an rvalue
   // ...
}

btw:为了清楚起见,我删除了一些内容,例如内联,constexpr,NO_EXCEPT和该函数的主体

我了解了当模板参数是指针(_Ty*),引用(_Ty&),通用引用(_Ty)时如何推导类型以及其类型所在本身(_Ty)。在这种情况下,它是一个引用,但在其前面添加了removed_reference<_Ty>::type_Ty和引用通过对remove_reference的调用来拆分。编译器如何确定_Ty的类型?

函数模板必须使用传递给函数的参数来确定模板参数(当未在函数调用中显式定义它们时),但是在这种情况下,remove_reference也是需要确定类型的类模板。 _Ty也是如此。对我来说,这几乎像个陷阱22,因为std::forward需要使用其函数参数来找出_Ty,但是其函数参数std::remove_reference<_Ty>必须已经知道_Ty是什么。这一切告诉我,我对模板的工作方式有一个错误的了解,但是我不知道在哪里。

3 个答案:

答案 0 :(得分:4)

  

编译器如何确定_Ty的类型?

不是。 std::forward用于显式提供的类型。它是通过接受类型为std::forward的{​​{1}}的函数参数来实现的,其中typename remove_reference<_Ty>::typenon-deduced context中。编译器不能推断出它。

转发参考的典型用法如下:

_Ty

严格来说,template<typename T> void foo(T&& t) { std::forward<T>(t); } 只是对以上std::forward进行强制转换的语法糖。 reference collapsing确实发挥了所有魔力,但是对T&&的裸露投递并没有传达与命名运算符一样清晰的转发意图。这就是T&&存在的原因。

答案 1 :(得分:3)

它不能演绎。这就是为什么当您使用public abstract class test { int count; public test(){ count(); count(); System.out.println("test" + this.count); } abstract void count(); } public class derive extends test{ int count; public derive(){ System.out.println("derive"); } @Override public void count(){ count++; } } public static void main(String[] args) { derived o = new derived(); } 时,必须为其指定模板参数:

std::forward

这与std::forward<T>(t); 相反,后者确实可以得出结论,并且通常这样使用:

std::move

答案 2 :(得分:2)

  

std::move(t); 如何推断std::forward的类型?

_Ty 没有一种类型。 Ty 一种类型(模板参数)。编译器推断类型。

  

编译器如何确定Ty的类型?

必须显式传递模板参数。

如果推断出类型,则:

_Ty

将传递一个左值,因为template<class T> void foo(T&& t) { bar(std::forward(t)); } 是一个左值。但是我们想传递一个右值,因为t是右值引用。由于推论起反作用,因此使用t技巧将其禁用,我们必须正确编写:

remove_reference<_Ty>::type&