2015-06-28 139 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