Search code examples
c++inheritancemultiple-inheritancediamond-problem

Diamond of death and Scope resolution operator (c++)


I have this code (diamond problem):

#include <iostream>
using namespace std;

struct Top
{
    void print() { cout << "Top::print()" << endl; }
};

struct Right : Top 
{
    void print() { cout << "Right::print()" << endl; }
};

struct Left : Top 
{
    void print() { cout << "Left::print()" << endl; }
};

struct Bottom: Right, Left{};

int main()
{
    Bottom b;
    b.Right::Top::print();
}

I want to call print() in Top class.

When I try to compile it I get error: 'Top' is an ambiguous base of 'Bottom' on this line: b.Right::Top::print(); Why is it ambiguous? I explicitly specified that I want Top from Right and not from Left.

I don't want to know HOW to do it, yes it can be done with references, virtual inheritance, etc. I just want to know why is b.Right::Top::print(); ambiguous.


Solution

  • Why is it ambiguous? I explicitly specified that I want Top from Right and not from Left.

    That was your intent, but that's not what actually happens. Right::Top::print() explicitly names the member function that you want to call, which is &Top::print. But it does not specify on which subobject of b we are calling that member function on. Your code is equivalent conceptually to:

    auto print = &Bottom::Right::Top::print;  // ok
    (b.*print)();                             // error
    

    The part that selects print is unambiguous. It's the implicit conversion from b to Top that's ambiguous. You'd have to explicitly disambiguate which direction you're going in, by doing something like:

    static_cast<Right&>(b).Top::print();