消除多重继承的歧义
使用模板基类处理多重继承时,会出现关于不明确成员函数解析的潜在问题。考虑以下场景:
template
class Base {
public:
template
typename std::enable_if::value>::type foo() {
std::cout 这里,函数 foo() 仅当模板参数与类型包中的其中一种类型匹配时才可调用。现在,如果派生类从具有不重叠类型集的多个基类继承,则编译器在解析 foo() 调用时可能会遇到歧义。
struct Derived: public Base,
public Base
{};
在这种情况下,调用 Derived().foo() 理想情况下会从 Base 调用 foo() 成员函数。然而,GCC 和 Clang 都报告了歧义。
为什么编译器无法解决歧义
由于成员函数查找的合并规则而出现编译错误。根据C标准,如果派生类本身没有声明成员函数,则查找过程依次搜索基类。然而,如果基类中的声明集不同,合并就会变得不明确。
在给定的场景中,派生类 Derived 没有显式声明 foo(),因此编译器必须合并来自两个基类。由于基类包含 foo() 的不同声明集,因此合并会导致歧义。
解决方案
要解决此歧义,一种选择是使用 using 声明在派生类中显式导入所需的成员函数。但是,这需要用户添加这些声明,这对于大型类型列表来说可能很冗长且不切实际。
struct Derived: public Base,
public Base
{
using Base::foo;
using Base::foo;
};
或者,可以使用辅助类来收集并合并所有基类的成员函数,从而允许派生类直接访问它们。
template
struct BaseCollector : Bases...
{
using Bases::foo...;
};
struct Derived : BaseCollector , Base>
{};
通过这种方法,用户不需要添加任何额外的声明来解决歧义。 BaseCollector 类有效地合并了所有基类的声明集,使 foo() 函数可用于派生类而不会产生歧义。
免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。
Copyright© 2022 湘ICP备2022001581号-3