2013-01-31 18 views
15

考慮下面的C++程序在C++ 11 make_pair(_Ty1 && _Val1,常量_Ty2&_Val2)重大更改

#include<map> 
#include<iostream> 
int main() { 
    int a = 5, b = 7; 
    auto pair = std::make_pair<int, int>(a,b); 
    return 0; 
    } 

gcc-4.7.2 fails與不同的錯誤使用VC11和也,但它似乎是相關的,VC11錯誤信息是更有意義的

You cannot bind an lvalue to an rvalue 

我從這次失敗明白的是

  1. VC11和我增刊ose gcc-4.7.2只有一個實現std :: make_pair make_pair(_Ty1&& _Val1, const _Ty2& _Val2),它只能接受右值引用。之前的VC++版本示例VC10有兩個版本,一個接受左值和另一個右值引用
  2. Rvalue引用不能用於初始化非const引用,即int & a = b * 5無效。
  3. 我本來可以使用std::movelvalue轉換爲rvalue參考,並且調用會成功。
  4. 由於std::make_pair爲每個參數接受兩種不同的類型,在所有可能的情況下,模板參數分辨率可以解析參數的類型,並且不需要明確指定類型。

這種情況似乎微不足道和不兼容性可以很容易地通過刪除明確的類型,使定義爲

auto pair = std::make_pair(a,b); 
  • 現在可以解決,我的問題是,什麼是去除驅動因素庫中的左值實現?
  • 是否有可能知道任何其他庫函數已被類似的方式改變?
  • 如何處理這些情況時,我需要針對多個編譯器,如g ++,CC,aCC,XL C++編譯器尚未升級或編譯器不支持右值引用和移動語義。
+2

那麼,它不是一個突破性的改變,因爲誰在地球上使用具有顯式模板實例的'std :: make_pair'?它*明確設計*從自動類型扣除中獲利。所以很少有人會寫'std :: make_pair '來支持'std :: make_pair',所以沒有太多的代碼可以被破壞。那麼,不錯,找到。 –

+1

不幸的是,我遇到了指定顯式類型的代碼。 – Abhijit

+0

我相信這是在[http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43785](http://gcc.gnu.org/bugzilla/show_bug.cgi? ID = 43785) – Nevin

回答

19

std::make_pair存在的唯一目的是利用類型推導以避免輸入類型的名稱。這就是爲什麼只有一個重載(並且它應該需要兩個universal references,而不是一個通用引用和一個左值對const的引用,因爲VC似乎認爲)。

template <class T1, class T2> 
constexpr pair<V1, V2> make_pair(T1&& x, T2&& y); 

如果您想明確鍵入類型,則可以使用pair構造函數。這是更短......

auto pair = std::pair<int, int>(a,b); 
+0

謝謝你的回答。我通過艱難的方式瞭解了上述事實。順便說一句,你能解釋一下「通用參考」的含義嗎?這個詞對我來說是新的。你是否也購買過類似的其他庫函數? – Abhijit

+0

@Ahhijit我添加了一個鏈接到斯科特邁爾的解釋(他提出了這個詞)。如果您不使用類型扣除,任何其他的庫函數(利用類型扣除)都可能不起作用。它們通常是'make_something'的形式,比如'make_tuple'。重點是它們不適用於顯式類型,因爲它們對顯式類型沒有用處。 –

+1

@Ahhijit清楚地說,「通用參考」只是一個口語詞彙。它們實際上只是右值引用,但是由於模板類型推導和引用崩潰規則,它們有一個有趣的屬性 - 它們有時表現得像左值引用和其他時候像右值引用。想想看,我們應該稱之爲左值右值對偶*。 –

18

當你做std::make_pair<int, int>,你迫使模板參數T1T2既可以推導出int。這給你的功能爲std::pair<int,int> make_pair(int&&, int&&)。現在這些參數只能取右值,因爲它們是右值引用。

但是,當T1T2的類型正在通過模板類型推導推導出來時,它們充當「通用參考」。也就是說,如果他們收到一個左值參數,他們將是左值引用,如果他們收到右值參數,他們將是右值引用。這使得make_pair能夠完成完美的轉發。

所以問題是,不要明確地給出模板類型參數。 make_pair的整點是它自己推導出類型。如果你命名這些類型,它不能再做完美的轉發,並且會失敗左值參數。