让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& ?
让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& ?
的类型推演默认规则参考类型永远不可能是扣除的结果。给定此代码,
template <class T>
void bar(T par);
bar(0);
int a;
bar(a);
int &b;
bar(b);
所有3个电话将呼叫foo<int>
。也就是说,T
推导为int
而par
的类型为int
。
转发的引用通过简单添加一个规则的工作:当用于一个转发参考的类型扣(即,参数T&&
的用于推导T
)参数是X
类型的左值,类型X &
用于代替X
进行扣除。
请注意,这意味着给定类型X
,只有X
或X &
可以是类型扣除的结果; 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 &
。
foo(0); //是T这里是int还是int & &?
安int
。
int a = 0; (a); //是T这里int还是int &?
一个int&
。
像您
template< typename T >
void foo(T&& a){}
什么在推断上下文表达T&&
即T的基础上,提供的参数推断,是受 reference collapsing rules。
总之;
如果所提供的参数是一个左值type
类型的,T&&
将扩大到type& &&
坍塌到type&
如果所提供的参数是type
类型的右值,T&&
将展开至type &&
,折叠至type&&
注意,两者都是引用,如果你需要触发另一个函数的右值 超载,你需要做的std::forward<T>(a)
您可以通过使用不同类型的特征,如HTTP尝试:// EN。 cppreference.com/w/cpp/types/is_reference或std :: is_same ..并用std :: add_lvalue_reference之类的东西建立类型,然后看看这些特征的值是什么 – xaxxon
下面是一个例子,所以你可以看到一种方式自己测试一下:https://wandbox.org/permlink/51APJ9Pr4fsweWrF – xaxxon
这里有一个调试类型的技巧:'template class TD;',然后在foo中使用:'TD ();'。由于'TD'没有定义,编译器会发出抱怨,并且在错误消息中,一个好的编译器会显示'T'的类型。 –
geza