模板类实例的多重继承以及对成员函数的访问
Multiple inheritance from instantiations of template class and what about access to member functions
让我们看看代码:
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<C>:size,忽略其余部分并使用此项。
有人能告诉我哪个编译器根据C++标准做正确的工作吗?
报告时间https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66698
最佳,Artur
这是一个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]
根据标准的成员查找算法,尽管使用了贴花,但您应该会得到相同的结果:
110.2/3:(…)在声明集中,using声明被它们指定的成员替换,type声明(包括注入的类名)被它们指定的类型所替换。
我找不到与这个bug完全匹配的。我建议你报告一下。
相关文章:
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 将公共但非静态的成员函数与ALGLIB集成
- 使用指向成员的指针将成员函数作为参数传递
- 将重载的成员函数传递给函数模板
- 我不小心调用了一个没有自己类对象的成员函数.但这是怎么回事呢
- 如何在C++中使用非静态成员函数作为回调函数
- C++错误C2600:无法定义编译器生成的特殊成员函数(必须首先在类中声明)
- 关联容器的下界复杂性:成员函数与非成员函数
- 在 C++ 中用派生类型重写成员函数
- 链表的泛型函数remove()与成员函数remove)
- 如何将lambda作为模板类的成员函数参数
- constexpr构造函数需要常量成员函数时出现问题
- 将自由函数绑定为类成员函数
- 区分非成员函数和头文件中的成员函数
- 如何从子成员函数修改父公共成员变量
- 保留对其他类的成员函数的引用
- 在运算符重载定义中使用成员函数(const错误)
- 内联如何影响模块接口中的成员函数
- 将成员函数指针作为参数传递给模板方法