2015-06-28 164 views
4

讓我們來看看代碼:多重繼承

template <typename C> 
class S { 
public: 
    void add (C c) { ++cnt; } 
    size_t size() const { return cnt; } 

private: 
    size_t cnt {}; 
}; 

struct Foo1 {}; 
struct Foo2 {}; 
struct Foo3 {}; 

class Z : public S<Foo1>, public S<Foo2>, public S<Foo3> { 
public: 
    using S<Foo1>::add; 
    using S<Foo2>::add; 
    using S<Foo3>::add; 

    using S<Foo1>::size; // (1) 
    using S<Foo2>::size; // (2) 
    using S<Foo3>::size; // (3) 
}; 

和使用情況是這樣的:

Z z; 

z.add (Foo1 {}); 
z.add (Foo1 {}); 
z.add (Foo2 {}); 

cout << z.size() << endl; 

此代碼編譯罰款gcc-5.1(C++ 11),但是這個代碼不能在clang-3.5下編譯(C++ 11 - 對不起,我沒有clang的新版本)。

鐺產生「錯誤:調用成員函數‘尺寸’不明確」這基本上是(從我的觀點來看)是正確的,但GCC編譯它,並返回。

好,但這裏更有趣,如果我切換行的順序標註評論(1)和(2),得到的東西是這樣的:

using S<Foo2>::size; // (2) 
using S<Foo1>::size; // (1) 

的代碼仍然編譯海合會其結果是:。你可以想象,如果你在這兩行之前寫行(3),你將得到。

所以,從我所看到的,GCC被首先使用的小號<Ç> ::大小聲明,忽略它們的休息和使用這一個。

有人能告訴我哪個編譯器根據C++標準做了正確的工作嗎?

報道在https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66698

最佳, 阿圖爾

+0

[Wandbox鏈接](http://melpon.org/wandbox/permlink/EMKWrvy558kzZmQD)。看起來像是4.6.4中的錯誤。 –

+0

顯然,你的代碼是不明確的,不應該編譯。 clang報告的錯誤是正確的。 MSVC也報告無效的歧義。你應該報告錯誤。 – Christophe

回答

1

這是一個gcc的bug。鏗鏘和MSVC正確地標記歧義。

如果去掉3條using語句,編譯失敗(因爲它應該),因爲模棱兩可的:

prog.cpp:39:12: error: request for member 'size' is ambiguous 
    cout << z.size() << endl; return 0; 
      ^
prog.cpp:9:12: note: candidates are: size_t S<C>::size() const [with C = Foo3; size_t = unsigned int] 
    size_t size() const { cout<<typeid(C).name()<<endl; return cnt; } 
      ^
prog.cpp:9:12: note:     size_t S<C>::size() const [with C = Foo2; size_t = unsigned int] 
prog.cpp:9:12: note:     size_t S<C>::size() const [with C = Foo1; size_t = unsigned int] 

根據標準成員查找算法,儘管使用decalartions你應該得出同樣的結果:

10.2/3: (...) In the declaration set, using-declarations are replaced by the members they designate, and type declarations (including injected-class-names) are replaced by the types they designate.

我找不到這個錯誤的完全匹配。我建議你report it