请解释自动类型推导与移动语义一起使用时的工作原理:
#include <iostream>
template <typename T>
struct A {
static void type() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
float& bar() {
static float t = 5.5;
return t;
}
int foo() {
return 5;
}
int main() {
auto &&a1 = foo(); // I expected auto -> int (wrong)
auto &&a2 = bar(); // I expected auto -> float& (correct)
A<decltype(a1)>::type();
A<decltype(a2)>::type();
}
输出结果为:
static void A<T>::type() [with T = int&&]
static void A<T>::type() [with T = float&]
答案 0 :(得分:3)
auto&&
(就像函数模板参数中T&&
一样T
是该函数模板的模板参数)遵循与其他扣减略有不同的规则 - 它是&#39}非正式地称为&#34;通用参考。&#34;
我们的想法是,如果初始化者是X
类型的左值,则auto
会推断为X&
。如果它是X
类型的右值,则auto
会推断为X
。在这两种情况下,都会正常应用&&
。根据参考折叠规则,X& &&
变为X&
,而X &&
仍为X&&
。
这意味着,在a1
案例中,auto
确实已推断为int
,但a1
自然会被声明为int&&
类型,而且decltype(a1)
#39; s auto
给你的东西。
与此同时,a2
中的float&
为a2
,decltype(a2)
的类型也是auto -> int
,a1
再次确认。< / p>
换句话说,您希望第一种情况中的auto &&a1
是正确的,但auto a1
的类型是{{1}},而不只是{{1}}。
答案 1 :(得分:2)
auto &&a1 = foo();
foo()
的返回类型是int。由于您将a1声明为auto&&
,因此它会扩展为int&&
,这就是您获得的a1类型。
auto &&a2 = bar();
bar()
的返回类型是浮动&amp ;.由于您将a2声明为auto&&
,因此它会扩展为float& &&
并按照规则转换为float&
。
This answer解释了通用参考扩展的规则:
&& -> &&
&& & -> &
& && -> &
&& && -> &&