消除多个继承类成员的歧义
考虑以下可变参数基类模板:
<code class="cpp">template <typename... Types> class Base { public: template <typename T> typename std::enable_if<Contains<T, Types...>::value>::type foo() { std::cout << "Base::foo()\n"; } };
foo()只能使用与类型包中的类型之一匹配的模板参数来调用成员。现在,让我们定义一个具有不重叠基类型的派生类:
<code class="cpp">struct Derived : public Base<int, char>, public Base<double, void> {};</code>
调用 Derived().foo
为什么编译器无法解决歧义:
成员查找 [class.member.lookup] 的合并规则指出,当派生类具有空声明集(无成员),必须合并所有基类的查找集。在我们的例子中,基类具有不同的声明集,因此合并失败。
解决方案:
为了避免这种歧义,我们可以向派生类添加 using 声明class:
<code class="cpp">struct Derived : public Base<int, char>, public Base<double, void> { using Base<int, char>::foo; using Base<double, void>::foo; };</code>
通过在派生类中引入 foo 的重载,我们有效地绕过了合并规则。
使用收集器类:
或者,我们可以使用模板类来聚合来自所有基类的 using 声明:
<code class="cpp">template <typename... Bases> struct BaseCollector; template <typename Base, typename... Bases> struct BaseCollector<Base, Bases...> : Base, BaseCollector<Bases...> { using Base::foo; using BaseCollector<Bases...>::foo; }; struct Derived : BaseCollector<Base2<int>, Base2<std::string>> {};</code>
这种方法在 C 17 中编译效率更高,因为它允许对 using 声明进行包扩展。
以上是为什么在 C 中调用可变参数模板成员函数时会出现多重继承歧义?的详细内容。更多信息请关注PHP中文网其他相关文章!