14

示例代碼:爲什麼可變參數函數不能「吃」C++ 11中的列表初始化參數?

#include <unordered_map> 

int main() { 
    std::unordered_map<int, std::pair<int, int>> map; 

    map.emplace(1, {1, 1}); 

    return 0; 
} 

emplace()有簽名,如:

template <class... _Args> 
pair<iterator, bool> emplace(_Args&&... __args); 

gcc說,功能expectes 0參數 - 2提供的。 clang表示函數需要1個參數 - 2提供。

我甚至不明白 - 這個代碼有什麼問題?

回答

12

問題是{1, 1}不是一個表達式,也沒有類型。由於它沒有類型,因此無法推導到模板參數列表中。它們都不是正確的,因爲這個問題與提供的參數數量無關。

+0

'map.emplace(1,std :: pair {1,1})'的作品,不是嗎? – Massa

+0

@Jefffrey:不,「{...}」不是一個表達式。第一個是「自動扣減」的特殊框架,它本來不應該存在(並且希望在未來的某個時候可能會被刪除),第二個是從braced-init-list中構建的。 – Xeo

+0

@Massa:是的,這就足夠了。 – Puppy

7

我甚至不明白 - 這個代碼有什麼問題?

由於某些不清楚的原因,初始化器列表參數是一個未推導的上下文,請參閱initializer_list and template type deduction。這是因爲C++ 11標準的§14.8.2.5/5這樣說。我不知道這個看似不一致,違反直覺的行爲的理由要麼,但我們並不孤單:

至於你的情況,也許最簡單的修復方法是:

map.emplace(1, std::make_pair(1, 1)); 
+0

原因並不明顯 - 告訴我,什麼樣的'initializer_list'應該是{1,「hi」}'? – Xeo

+2

@Xeo我沒有得到你的例子。 'auto x = {1,「hi」};'也是編譯時錯誤,所以你試圖創建什麼? – Ali

+0

@Xeo我想如果有的話,原因一定是別的。我的猜測是允許對函數模板參數進行這種推導可能會適得其反。雖然,我沒有拿出一個例子。 – Ali

相關問題