2016-04-27 55 views
1

我不知道爲什麼編譯器會給我關於模板實例化的警告。std :: forward帶有模板化重載函數

那是一個代碼段它運行得很好並正確輸出左值/右值:

//template<typename T> 
void overloaded(const /*T*/std::string& in) 
{ 
    std::cout << "lvalue" << std::endl; 
} 

//template<typename T> 
void overloaded(/*T*/std::string&& in) 
{ 
    std::cout << "rvalue" << std::endl; 
} 

template<typename T> 
void pass(T&& in) 
{ 
    overloaded(std::forward<T>(in)); 
} 

int main() 
{ 
    std::string a; 
    pass(a); 
    pass(std::move(a)); 
    getchar(); 
} 

但我需要與模板類型使用它。因此,修改「重載」功能

template<typename T> 
void overloaded(const T& in) 
{ 
    std::cout << "lvalue" << std::endl; 
} 

template<typename T> 
void overloaded(T&& in) 
{ 
    std::cout << "rvalue" << std::endl; 
} 

給出模板實例警告,(當我其清晰T應當的std :: string),以及控制檯輸出第一右值,而不是2倍左值的。

我在做什麼錯了?

+0

適合我。 http://coliru.stacked-crooked.com/a/fc00c140c9a8e208 – erip

+0

'T &&'是一個轉發引用,即如果'T'是一個類型模板參數,它不再是一個常規的右值引用 –

回答

1

模板,如T&&是特殊的。他們被稱爲「轉發參考」。他們有相同功能的特殊扣規則:

template<typename T> 
void overloaded(T&& in) 

假設一下,如果overloaded不會過載。如果您將類型std::string的左值表達式傳遞給overloaded,則T將推斷爲std::string&。如果將std::string類型的右值表達式傳遞給overloaded,則T將推導爲std::string。你可以用這些知識來做到這一點:

template<typename T> 
void overloaded(T&& in) 
{ 
    if (std::is_lvalue_reference<T>::value) 
     std::cout << "lvalue" << std::endl; 
    else 
     std::cout << "rvalue" << std::endl; 
} 

在一般情況下,它是一個反模式超載T&&模板與別的。這些特殊模板在您想要捕捉所有內容時派上用場。

+0

哇,我完全沒有意識到那!謝謝! – Pancake