5

您能解釋STL容器如何處理具有空初始化程序列表的賦值運算符?賦值運算符爲空inizializer_list

時我會做這樣的事情:

vector<int> v; 
v = { }; 

被調用的函數是

vector& operator= (initializer_list<value_type> il); 

但:

vector& operator= (vector&& x); 

,另一方面,當我會做類似於我自己的課程:

struct A { 
    A& operator= (const A&) { return *this; } 
    A& operator= (A&&) { return *this; } 
    A& operator= (initializer_list<int>) { return *this; } 
}; 

/* ... */ 

A a; 
a = { }; 

代碼沒有就VS2013,並說:

error C2593: 'operator =' is ambiguous 

如果列表不是空的,它工作得很好,它只是調用與初始化列表的功能。只有當列表爲空時,纔會出現問題,它在向量上調用右值賦值運算符,在我的類上出現錯誤。

如何在矢量和其他容器中處理這種情況?

+1

無論'gcc'也不'clang'具有相同的錯誤但用[vs]確認錯誤(http://rextester.com/ZWD57818)。 –

+0

[無法重現](http://coliru.stacked-crooked.com/a/cd78ac29f69fdc05)。 – Shoe

+0

g ++和clang ++明確地選擇'operator ='的'initializer_List '重載。我認爲這是正確的:根據[over.ics.list],這個重載的轉換等級應該是精確匹配。對於引用重載,必須創建一個臨時對象,所以引用(可能)不會直接綁定;因此轉換順序是用戶定義的轉換。 (請注意[over.ics.ref]中定義的部分沒有提及list-init;它可能是低級指定的。) – dyp

回答

3

這似乎是一個錯誤鐺(see it live)和gcc(see it live)接受這一方案,並選擇的std :: initializer_list超載這看起來是正確的,因爲這是一個精確匹配,這是覆蓋在從示例的C++ draft standard部部分13.3.3.1.5列表的初始化序列段落:

void f(std::initializer_list<int>); 
f({1,2,3}); // OK: f(initializer_list<int>) identity conversion 
f({’a’,’b’}); // OK: f(initializer_list<int>) integral promotion 
f({1.0}); // error: narrowing 

我們有一個身份轉換這是一個完全匹配

對於參考過載我們去一段它說(重點煤礦前進):

否則,如果該參數是一個參考,請參閱13.3.3.1.4。 [注意:本部分的規則將適用於初始化參考的基礎臨時。 - 注意]

指示臨時創建一個然後我們可以將規則應用於生成的臨時。這將是一個用戶定義的轉換這比完全匹配更糟糕。

所以這應該是不明確的。

更新

看起來像有與此相關的兩個活動的錯誤:

+0

我同意你的結論,但是我認爲(正如在OP的評論中所討論的那樣),13.3.3.1.4和8.5.3都不能用於發現它是直接綁定還是間接綁定(他們討論的是參數表達式)。相反,我會說13.3.3.1.5/6中的註釋(關於引用的那個)表示從{{}(通過8.5.4,按照13.3.3.1排列爲UDC)創建了一個臨時表。 5/5),然後直接綁定(8.5.3「如果初始化表達式是類prvalue」,按照13.3.3.1.4/1排列爲精確匹配)。另請參見13.3.3.1.1/3 – dyp

+0

@dyp我明白你的意思,但我認爲你的意思是'13.3.3.1.5/5'中的註釋*注意:本節中的規則將適用於初始化潛在的臨時參考。 - 結束註釋*。 –

+0

編號取決於你使用的是哪個草稿;)最近來自github回購,他們已經將'initializer_list'和數組部分分成兩段。 – dyp