加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 来自模板类实例化的多重继承以及对成员函数的访问权限

发布时间:2020-12-16 07:12:58 所属栏目:百科 来源:网络整理
导读:我们来看看代码: template typename Cclass 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 SFoo1,public SFoo2,public SFoo3 {pub
我们来看看代码:

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).

Clang产生“错误:调用成员函数’大小’是模糊的”,这基本上(从我的观点来看)是正确的,但是gcc编译它并返回2.

好的,但是这里更有趣,如果我切换标记为注释(1)和(2)的行的顺序,得到这样的东西:

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

代码仍然在gcc上编译,结果是:1.

你可以想象,如果你在这两个之前写第(3)行,你就会得到0.

所以,从我看到的,gcc首先使用S< C> :: size的声明,忽略其余部分并使用这个.

根据C标准,有人能告诉我哪个编译器正在做正确的工作吗?

报道于https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66698

最好,
阿图尔

解决方法

这是一个gcc bug. Clang和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.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读