c++ - 模板类实例化的多重继承以及对成员函数的访问

标签 c++ c++11 gcc clang

让我们看一下代码:

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 产生“错误:对成员函数‘size’的调用不明确”这基本上(从我的角度来看)是正确的,但是 gcc 编译它并返回 2

好吧,但这里更有趣,如果我调换标有注释 (1) 和 (2) 的行的顺序,得到如下结果:

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

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

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

因此,据我所知,gcc 首先使用 S::size 的声明,忽略其余部分并使用这个。

谁能告诉我哪个编译器根据 C++ 标准正确地工作?

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

最好的, 阿图尔

最佳答案

这是一个 gcc 错误。 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]

根据标准的成员查找算法,尽管使用了声明你应该得到相同的结果:

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 .

关于c++ - 模板类实例化的多重继承以及对成员函数的访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31104690/

相关文章:

c++ - struct _stack* 和 Digit::struct_stack* 中的一些问题

c++ - 内存对齐高于最大对齐 alignas malloc

c++ - 如何在堆栈上放置新的

c - C 中 'complex' 的默认类型

c - 基于 GCC 的 SIGSEGV 错误?

c++ - Qt-5.14.0:QML下的Vulkan导致std::system_error::互斥锁失败

c++ - 可修改字符串文字的用例

c++ - 我在链表实现中对 std::shared_ptr 和 std::unique_ptr 做错了什么?

c++ - 根据类模板参数淘汰类模板构造函数

python - 命令 'llvm-gcc-4.2' 失败,退出状态 1