2011-01-21 75 views
23

我創建了一個模板如下爲什麼沒有我的模板接受初始化列表

template<typename T> 
void f(T const& t) { } 

我想爲這是由容器也由初始化列表調用。我認爲這將是initializer_list<int>,當調用如下。

f({1, 2, 3}); 

但GCC的行爲如同它不符合標準的

m.cpp: In function 'int main()': 
m.cpp:6:25: warning: deducing 'const T' as 'const std::initializer_list<int>' 
m.cpp:4:6: warning: in call to 'void f(const T&) [with T = std::initializer_list<int>]' 
m.cpp:6:25: warning: (you can disable this with -fno-deduce-init-list) 

誰能解釋我如何才能讓沒有警告這項工作?謝謝!

+5

嗯似乎不幸的是,SO認爲'initializer_list'標籤是'initializer-list'的同義詞。-.- C++ 0x會掉眼淚! –

+0

AFAICS,它沒有被定義爲http://stackoverflow.com/tags/initializer-list/synonyms的同義詞。是否有一些內置邏輯用'x-y'替換'x_y'? – sbi

+0

哦,沒關係,我剛纔看到http://meta.stackexchange.com/questions/75798/unfortunate-auto-detection-of-synonyms-for-initializer-list – sbi

回答

25

像{1,2,3}這樣的「事物」不符合表達式的條件。它沒有類型。因此,沒有類型扣除完成。但是的C++ 0x使得對 '自動' 一個明確的異常,所以

auto x = {1,2,3}; 

實際工作和decltype(X)將initializer_list<int>。但這是一個只適用於汽車的特殊規則。我想他們想讓這樣的循環

for (int x : {2,3,5,7,11}) { 
    ... 
} 

工作,因爲這種循環利用特殊規則。

作爲解決這個問題,你可以添加一個initializer_list<T>過載爲「包裝」:

template<class T> 
inline void outer(initializer_list<T> il) { 
    inner(il); 
} 

我沒有測試這一點,但我目前的理解是,它應該工作。

+1

+1和是正確的。 –

+2

提到的特殊規則是在7.1.6.4'auto'說明符中[dcl.spec.auto] –

+0

'C++ 0x爲'auto''提供了一個明確的例外是的,無論是你所展示的任務類語法還是還有'auto something {a,b,c}'形式。後者一直是後面的一個不一致的痛苦,後者現在只能用C++ 17來解決,其中'auto something {blah}'沒有'='符號意味着_'創建'decltype(blah) ',從'blah'_初始化 - '_'的當前含義不是''用'blah''_創建一個與'blah''_相同類型的元素的'initializer_list'。最後!但是,這意味着對受影響的代碼庫進行了大量更新。 :C –

3

好,the documentation

此選項存在,因爲這個扣除的擴展,在C++ 0x中工作草案目前的規範,並有潛在的重載問題的一些擔憂。

此信息可能會過時(根據它在2008年最後更新的來源)。據我瞭解,扣除包括在GCC中,但期望標準的後期草案將刪除該規則,或者至少限制該規則。

1

任何人都可以解釋如何使這項工作沒有任何警告?

我不知道,如果this是指你所援引確切的代碼,或者如果你只是想知道你是如何實例化一個初始化列表中的函數模板,而不會觸發警報,但如果是後者,如果問題僅僅是演繹正確的類型,你可能避免它通過只調用

f<initializer_list<int>>({1, 2, 3}); 

它不漂亮,但它可能避免該警告沒有與編譯器命令行參數擺弄。

我可能會在附近發表評論,這說明你不依賴編譯器推導出某些GCC版本中的弱點所導致的正確類型。

相關問題