Search code examples
c++templatesmultiple-inheritance

Default for resolving ambiguous access


Consider the following classes:

class VisitableNode {
public:
    virtual void Visit();
};

class VisitableGraph {
public:
    virtual void Visit();
};

class OtherNode {
};

class OtherGraph {
};

template<class G, class N>
class GraphNode : public G, public N {
};

class MyVisitableGraph : public GraphNode<VisitableGraph, VisitableNode> {
};

class MyOtherGraph : public GraphNode<OtherGraph, OtherNode> {
};

MyVisitableGraph visitableGraph;
visitableGraph.Visit(); // Ambiguous access. Could be either VisitableGraph::Visit or VisitableNode::Visit.

MyOtherGraph otherGraph;

The ambiguous access issue can be solved with using inside MyVisitableGraph:

class MyVisitableGraph : public GraphNode<VisitableGraph, VisitableNode> {
    using VisitableGraph::Visit;
};

But, is there a way to resolve the ambiguity inside GraphNode instead? I can't just do using G:Visit, as then MyOtherGraph would not compile. Is it for example possible to specify that by default, G should have higher precedence than N in order to resolve ambiguities in GraphNode?


Solution

  • As suggested by @463035818_is_not_a_number, this answer gave a solution:

    template<class G, class N>
    class GraphNode : public G, public N {
    public:
        template<class = decltype(&G::Visit)>
        void Visit() {
            G::Visit();
        }
    };
    

    It loses the virtual specifier, so it might not always be usable. And it is very hacky, so I don't think I'll use it. A way to say that all ambiguities should be resolved by using G over N would have been nicer.