2017-10-04 46 views
4

foo是函数:理解型扣除普遍引用

template< typename T > 
void foo(T&& a){} 

什么类型将T推断为foo以下呼叫:

foo(0); // is T here int or int&& ? 

int a = 0; 
foo(a); // is T here int or int& ? 
+1

您可以通过使用不同类型的特征,如HTTP尝试:// EN。 cppreference.com/w/cpp/types/is_reference或std :: is_same ..并用std :: add_lvalue_reference之类的东西建立类型,然后看看这些特征的值是什么 – xaxxon

+0

下面是一个例子,所以你可以看到一种方式自己测试一下:https://wandbox.org/permlink/51APJ9Pr4fsweWrF – xaxxon

+2

这里有一个调试类型的技巧:'template class TD;',然后在foo中使用:'TD ();'。由于'TD'没有定义,编译器会发出抱怨,并且在错误消息中,一个好的编译器会显示'T'的类型。 – geza

回答

5

的类型推演默认规则参考类型永远不可能是扣除的结果。给定此代码,

template <class T> 
void bar(T par); 

bar(0); 
int a; 
bar(a); 
int &b; 
bar(b); 

所有3个电话将呼叫foo<int>。也就是说,T推导为intpar的类型为int

转发的引用通过简单添加一个规则的工作:当用于一个转发参考的类型扣(即,参数T&&的用于推导T)参数是X类型的左值,类型X &用于代替X进行扣除。

请注意,这意味着给定类型X,只有XX &可以是类型扣除的结果; X &&永远不会。

让我们来分析你的代码(我将重新命名,他功能参数,使之清楚,我指):

template <class T> 
void foo(T &&par); 

foo(0); 

int a; 
foo(a); 

在第一种情况下foo(0),参数是int类型的右值因此使用类型int来进行类型推断,这意味着T被推导为int(被称为的函数是foo<int>)并且par的类型是int &&

在第二种情况foo(a)中,自变量是类型int。转发参考规则将启动并使用类型int &进行推导。 T因此推导为int &(函数名为foo<int&>),并且par的类型为“int & &&”,其折叠为int &

1

foo(0); //是T这里是int还是int & &?

int

int a = 0; (a); //是T这里int还是int &?

一个int&

1

像您

template< typename T > 
void foo(T&& a){} 

什么在推断上下文表达T&&即T的基础上,提供的参数推断,是受 reference collapsing rules

总之;

  • 如果所提供的参数是一个左值type类型的T&& 将扩大到type& &&坍塌到type&

  • 如果所提供的参数是type类型的右值T&& 将展开至type &&,折叠至type&&

注意,两者都是引用,如果你需要触发另一个函数的右值 超载,你需要做的std::forward<T>(a)