2014-01-09 17 views
4

我發現Microsoft Visual C++編譯器和gcc-4.8.1(由ideone.com提供)之間存在差異。考慮以下SSCCE:複製初始化和顯式構造函數 - 編譯器差異

struct S 
{ 
    int x; 
}; 

class A 
{ 
public: 
    int x; 
    A(const S& s) : x(s.x) {} 
}; 

class B 
{ 
    int x, y; 

public: 
    template <typename T> explicit B(const T& t) : x(t.x), y(t.y) {} 

    B(const A& a) : x(a.x), y(0) {} 
}; 

int main() { 
    S s = {1}; 

    B b1 = s; // Compiles OK on MSVC++; 
      // Fails on gcc - conversion from ‘S’ to non-scalar type ‘B’ requested 

    B b2(s); // Fails on both - Error: y is not a member of S in B::B<S>(const T &) 
} 

我明白爲什麼行B b2(s);失敗 - 的explicit構造相匹配,所以它試圖;但是t.y不存在。精細。

但我不能確定是否允許B b1 = s; MSVC++是正確的,或者拒絕gcc是否正確。 MSVC++正在從A::A(const S&)構建一個臨時文件,並使用它通過B::B(const A&)初始化b1;我不知道爲什麼gcc錯誤。

哪個編譯器的權利?

(作爲一個音符後,如果刪除explicit兩種編譯器拒絕B b1 = s; - 大概是因爲模板構造函數現在是臨時的隱含建設公平的遊戲。)

編輯:從評論,它似乎MSVC++也拒絕在Visual Studio 2012中的B b1 = s;行,所以共識似乎是它真的是一個錯誤。在這種情況下 - 錯誤的性質是什麼?那個錯誤信息是什麼的意思是

+0

VS2012也會因'B b1 = s;'失敗。我相信失敗是正確的行爲。哪個VS沒有失敗? – egur

+0

有趣。我的版本是VS2010,所以它可能是一個固定的錯誤(當我們升級時,這可能會破壞我們的代碼)。不過,我仍然很想知道發生了什麼。 – Chowlett

+0

@egur - 2012年的錯誤信息是什麼? – Chowlett

回答

5

被盜從這個answer,標準表示:

12.3換算[class.conv]

4至多一個用戶定義的轉化率(或構造轉換函數)被隱式應用到單個值。

你試圖一步到位,S這需要轉換爲B執行兩個的構造函數,它接受一個A,然後又爲A的構造函數,它接受一個S。解決方法是首先將S轉換爲A

B b1 = static_cast<A>(s); 
+0

+1。但我認爲你過於誠實。 – SChepurin

+0

這顯然是正確的;但你可以爭辯說'S - > A'做一個臨時的,然後'A - > B'來複制初始化每一個用戶定義的轉換應用於不同的對象。另外,從'S'轉換爲非標量類型'B'的請求是什麼?試圖告訴我? – Chowlett

+0

@Chowlett結構/類是一種非標量類型。我認爲錯誤信息很混亂。 – 2014-01-09 11:12:05

相關問題