【问题标题】:How to resolve multiple inheritance ambiguities in C++如何解决 C++ 中的多重继承歧义
【发布时间】:2018-05-23 22:42:10
【问题描述】:

我有一个小程序如下:

#include <iostream>

template <typename T>
class X{
    public:
        bool something(){
            return true;
        }
};

class A: public X<A>{
};


class B: public A, public X<B>{
};


template <typename T>
bool use(T &t)
{
    return t.something();
}



int main()
{
    B b;
    std::cout << "use returned: " << use(b);
}

这不会编译,因为对于应该选择something() 的两个可能版本中的哪一个存在歧义:

In instantiation of 'bool use(T&) [with T = B]':
30:43:   required from here
22:20: error: request for member 'something' is ambiguous
6:14: note: candidates are: bool X<T>::something() [with T = B]
6:14: note:                 bool X<T>::something() [with T = A]
 In function 'bool use(T&) [with T = B]':
23:1: warning: control reaches end of non-void function [-Wreturn-type]

我的问题是,如果我唯一可以编辑的地方是 use() 的正文,我该如何解决这种歧义?

【问题讨论】:

  • 您可以将其转换为 X 或 A 对象。例如((A)t).something()
  • 我有点不确定演员阵容会是什么样子。只是好老(mytype)?
  • 是的((sometype)t).something() 确保您拥有正确的() 操作员顺序。
  • 如果这不起作用,请告诉我(我测试过它确实有效)我还有其他一些建议您可以尝试。
  • 你想调用哪个版本的东西?

标签: c++ templates inheritance methods ambiguous


【解决方案1】:

是的。例如,您可以将呼叫限定为something (godbolt):

template <typename T>
bool use(T &t)
{
    return t.A::something();
}

【讨论】:

    【解决方案2】:

    您可以为 T 从 X 派生然后在内部强制转换为 X 的情况添加模板“use”的特化。

    template <typename T>
    class X{
        public:
            bool something(){
                return true;
            }
    };
    
    class A: public X<A>{
    };
    
    
    class B: public A, public X<B>{
    };
    
    #
    # If class derives from X<T> make sure to cast to X<T> before calling something
    #
    template<typename T>
    typename std::enable_if<std::is_base_of<X<T>, T>::value, bool>::type use(T &t)
    {
         return static_cast<X<T>&>(t).something();
    }
    
    #
    # This gets run for everything that doesn't derive from X<T>
    #
    template<typename T>
    typename std::enable_if<!std::is_base_of<X<T>, T>::value, bool>::type use(T &t)
    {
         return t.something();
    }
    

    尽管必须检查语法,但这应该确保您在特殊情况下得到它,同时只允许一个“something”调用。

    【讨论】:

    • 更新了上面的代码进行编译。请注意,这允许您为 T 派生自具有“某物”方法的多个类的任何情况添加特化。您只需添加另一个专门和强制转换的模板。
    猜你喜欢
    • 2011-02-09
    • 2019-12-28
    • 1970-01-01
    • 2021-06-29
    • 2016-12-22
    • 2012-05-08
    • 1970-01-01
    相关资源
    最近更新 更多