我正在使用std :: is_same实用程序函数与rvalue和lvalue引用一起玩,并且遇到了一种奇怪的行为。
考虑这个函数模板,它检查变量t的类型。
我正在使用VS 2013:
struct Test {};
template < class T> void h(T && t)
{
cout << " Is type &&: " << std::is_same<decltype(t), T &&>::value << endl;
cout << " Is type &: " << std::is_same<decltype(t), T &>::value << endl;
}
我观察到以下输出:
h(Test()); // is type && : 1 is type & : 0
这是正常的,因为Test()是一个临时对象,参数h中的通用引用解析为r值引用(&amp;&amp;&amp;&amp; =&amp;&amp;)
但请考虑一下:
Test myTest;
h(myTest); // is type && : 1 is type & : 1 !!!
如果我写的话,结果相同:
Test &myTest = Test():
h(myTest); // is type && : 1 is type & : 1 !!!
与之相同:
Test &&myTest = Test():
h(myTest); // is type && : 1 is type & : 1 !!!
上午我错过了什么?对我来说这看起来像是一团糟:)在VS 2013中是否完全支持rvalue reference / decltype的功能?
感谢您的帮助
罗曼
答案 0 :(得分:4)
4611686014132420609
Overflow!
666013
fin>>c;
for (i=1;i<=c;i++,p=0){
fin>>a>>b;
p=a*b;
if (p/b==a)
fout<<p<<"\n";
else
fout<<"Overflow"<<"\n";
}
return 0;
}
在h内,T为Test myTest;
h(myTest); // is type && : 1 is type & : 1 !!!
,t为Test&
,即Test& &&
。进行测试时,Test&
为真,因为std::is_same<decltype(t), T &&>
为Test& &&
,而Test&
类型为t
。
Test&
也是如此,因为std::is_same<decltype(t), T &>
类型为t
,Test&
为T&
,即Test&&
。
仔细应用参考折叠规则有助于此。
有关为什么h()T内部为Test&
类型的原因。原因是它是唯一与实际参数匹配的T类型。 T不能简单地Test&
,因为Test&amp;&amp;不会绑定(匹配)类型Test
的左值(因为这是参数类型)。但是,由于引用了折叠规则,Test
将会出现。
答案 1 :(得分:1)
我将从这里开始:
template < class T> void h(T && t)
{
std::cout << " Is type &&: " << std::is_same<decltype(t), T &&>::value << '\n';
std::cout << " Is type &: " << std::is_same<decltype(t), T &>::value << '\n';
}
在第一次测试中,您询问decltype(t)
是否与T&&
相同。
对于变量,decltype(variable)
是变量的声明类型。看看如何声明t
- 它是T&&
。
并不令人惊讶,decltype(t)
与T&&
相同,因为T&& t
被声明为T&&
。
无论T
是什么,这都是正确的。所以无论你通过什么类型T
,你都会在那条线上得到真实。
抓住这个。明白这一点。您无法与T
匹配的类型可能会使第一行无法打印1
。如果你对第一行感到困惑,那就回到它正在做std::is_same< T&&, T&& >::value
的事实。无论T&&
的规则是什么,双方都是一样的。
但是,等等,你说,T&&
不是左值参考?嗯,通常。如果类型类型T
是引用类型,则应用引用折叠规则。当T&&
变为T=X&
而不是X&
时,X&&
。左值参考胜过右值参考。
这具有特殊的扣除规则,是转发引用(也称为通用引用)的权力。
当您将X
类型的左值传递给h
时,它会推导出T=X&
。
当您将X
类型的左值传递给h
时,它会推断T=X
。
在第一种情况下,T&&
变为X&
,而在第二种情况下变为X&&
。
在具体情况下,Test()
是Test
类型的右值,这意味着h(Test())
推导T=Test
,我们得到T&&
= {{1 } {while Test&&
= T&
。代码打印1然后为0,因为Test&
(又名T&&
,又名decltype(t)
)与Test&&
相同,但不是T&&
。
在第二个具体案例中,T&
将h(myTest)
作为左值(即使它被声明为myTest
,它也是左值,因为它有一个名称)。然后Test&&
为T
,Test&
为T&&
,Test&
为T&
。该函数打印出1然后为1,因为Test&
(又名T&&
,又名decltype(t)
)与Test&
和T&&
相同。
要解决您的问题,请执行以下操作:
T&
你得到了你期望的输出。