2014-03-27 50 views
4

請解釋如何自動類型推演作品與舉動語義當用於什麼`汽車&& i = FOO();'意味着

#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

你的輸出顯示'int'和'float'? – Brian

回答

3

auto&&(就像T&&在功能模板的參數中,其中T是該功能模板的模板參數)遵循與其他推導稍微不同的規則 - 它在非正式方面被稱爲「通用參考」。

想法是,如果初始化程序是X類型的左值,則auto推導爲X&。如果它是X類型的右值,則auto推導爲X。在這兩種情況下,&&然後正常應用。從參考摺疊規則,X& &&變爲X&,而X &&仍然爲X&&

這意味着,在您的a1情況下,auto確實推斷int,但a1然後自然地與int&&類型聲明,而這正是decltype(a1)給你。

與此同時,該在autoa2float&,所以是的a2類型,其中decltype(a2)再次證實。

換句話說,你的期望auto -> int在第一種情況下是正確的,但a1類型是auto &&a1,不只是auto a1

+0

有什麼我應該知道變量推導爲「鍵入&&」,或者他們總是會表現爲「類型」? (在這個例子中,一個「int &&」的行爲總是和普通的int相同) – Allan

+0

@Allan如果它是從一個prvalue初始化的,我想不出任何東西(除了'decltype'),你可以說出區別。但是,如果它引用的內容可以更改,則可以通過'int &&'引用觀察更改,但不會通過「int」副本。 – Angew

2

auto &&a1 = foo();

foo()返回類型爲int。由於您將a1聲明爲auto&&,因此它展開爲int&&,這就是您獲得的a1類型。

auto &&a2 = bar();

bar()返回類型是浮動&。由於您將a2聲明爲auto&&,因此它將展開爲float& &&,並按照規則轉換爲float&

This answer說明了通用的參考是如何擴展的規則:

&& -> && 
&& & -> & 
& && -> & 
&& && -> &&