Question

I have a host class, which takes two policies, sayhello and talk. The policy talk is a class template, which itself takes e.g. sayhello. The problem is that sayhello::saySomething is ambiguous in host2 (i tried to solve this diamond problem with virtual).

How can i resolve this ambiguity? Or is there in general a better design for such problems?

Example:

#include <iostream>

class sayhello {
protected:
    void saySomething(void) {
        std::cout<<"Hello!"<<std::endl;
    }
};

template<typename T>
class talk : private T {
protected:
    void doSomething(void) {
        T::saySomething();
    }
};

template<typename T>
class host1 : virtual T {
public:
    void hostAction(void) {
        T::doSomething();
    }
};

template<typename T, typename L>
class host2 : private T, private L {
public:
    void hostAction(void) {
        T::doSomething();
        L::saySomething();
    }
};

int main() {
    host1<talk<sayhello> > HOST1;
    HOST1.hostAction(); // ok that works

    host2<talk<sayhello>,sayhello> HOST2;
    HOST2.hostAction(); // error, ambiguity!

    return 0;
}
Was it helpful?

Solution

You are probably abusing inheritance, but just add a couple more virtual keywords in both talk and host2:

#include <iostream>

class sayhello {
protected:
    void saySomething(void) {
        std::cout<<"Hello!"<<std::endl;
    }
};

template<typename T>
class talk : virtual T {
protected:
    void doSomething(void) {
        T::saySomething();
    }
};

template<typename T>
class host1 : virtual T {
public:
    void hostAction(void) {
        T::doSomething();
    }
};

template<typename T, typename L>
class host2 : virtual T, virtual L {
public:
    void hostAction(void) {
        T::doSomething();
        L::saySomething();
    }
};

int main() {
    host1<talk<sayhello> > HOST1;
    HOST1.hostAction(); // ok that works

    host2<talk<sayhello>,sayhello> HOST2;
    HOST2.hostAction(); // error, ambiguity!

    return 0;
}

Live Example

OTHER TIPS

You could add a dummy class:

template<typename T> struct dummy : T {};

template<typename T, typename L>
class host2 : private T, private dummy<L> {
public:
    void hostAction(void) {
        T::doSomething();
        dummy<L>::saySomething();
    }
};

In some cases you will probably need to cast to L directly, which should work like this:

L& getL()
{
    return static_cast<L&>(static_cast<dummy<L>&>(*this));
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top