2016-11-11 40 views
0

有人可以帮助我理解为什么下面的代码型扣,而使用通用引用

template< typename T > 
void check() 
{ 
    std::cout << "unknow type" << std::endl; 
} 

template<> 
void check<int>() 
{ 
    std::cout << "int" << std::endl; 
} 

template<> 
void check<int&>() 
{ 
    std::cout << "int&" << std::endl; 
} 

template<> 
void check<int&&>() 
{ 
    std::cout << "int&&" << std::endl; 
} 

template< typename T > 
void bar(T&& a) 
{ 
    check<T>(); 
} 

int main() 
{ 
    bar(0); 

    int a = 0; 
    bar(a); 
} 

的输出

int 
int& 

,而不是

int&& 
int& 

从我的观点。看来,r值参考仍然是一个r值参考值和一个l值参考值alue引用,但是,似乎只有l值引用保留为l值引用,r值变为非引用值。 这背后的动机是什么?

+5

您正在使用'check ',而不是'检查';为什么您希望'&&'在您明确省略时出现? – ildjarn

+0

我预计'bar(0)'与'(0)'相同。当用'bar (0)'在我的代码中替换'bar(0)'时,输出实际上是'int && \ n int&'。 –

+3

“酒吧”的类型为“无效(T &&)”,“酒吧”的类型为“无效(T && &&)”(在参考折叠之前)。 – Oktalist

回答

4

bar(0);调用专业化bar<int>(int&&)T推导为int,所以check<T>()check<int>()是。参数类型为T&&,即int&&,但这是参数的类型,而不是类型T

这与非转发参考完全一致。如果定义:

template<typename T> void baz(T&); 

和你int类型,然后的一个左T被推断为int,不int&

这是特别的喜欢你的例子使用转发引用的唯一的事情称之为是为T&&该类型可以推断为左值参考,称之为R,在这种情况下,参数类型为R&&,与add_rvalue_reference_t<R>相同,这只是R。所以对于通话bar(a)调用专业化bar<int&>(int&)T被推断为int&

当你调用bar<int&&>(0)有一个明确的模板参数列表没有参数扣等Tint&&取代,因此参数类型T&&add_rvalue_reference_t<int&&>这只是int&&