#include <iostream>
#include <cassert>
class LibFoo;
class LibBar;
class IfaceA;
class IfaceB;
template <typename LIB> class BaseA;
template <typename LIB> class BaseB;
struct IfaceA
{
virtual ~IfaceA () {}
virtual operator BaseA<LibFoo> * () { return 0; }
virtual operator BaseA<LibBar> * () { return 0; }
virtual void doSomethingWith (IfaceB &) = 0;
};
struct IfaceB {
virtual ~IfaceB () {}
virtual operator BaseB<LibFoo> * () { return 0; }
virtual operator BaseB<LibBar> * () { return 0; }
};
template <typename LIB>
struct BaseA : IfaceA {
operator BaseA * () override { return this; }
void doSomethingWith (IfaceB &b) override {
doSomethingWithB(b);
}
void doSomethingWithB (BaseB<LIB> *b) {
assert(b);
doSomethingWithB(*b);
}
virtual void doSomethingWithB (BaseB<LIB> &b) = 0;
};
template <typename LIB>
struct BaseB : IfaceB {
operator BaseB * () override { return this; }
};
struct LibFoo {
class FooA {};
class FooB {};
};
struct ConcreteFooA : BaseA<LibFoo> {
void doSomethingWithB (BaseB<LibFoo> &) override {
std::cout << "ConcreteFooA::" << __func__ << '\n';
//...
}
LibFoo::FooA a_;
};
struct ConcreteFooB : BaseB<LibFoo> {
LibFoo::FooB b_;
};
struct LibBar {
class BarA {};
class BarB {};
};
struct ConcreteBarA : BaseA<LibBar> {
void doSomethingWithB (BaseB<LibBar> &) override {
std::cout << "ConcreteBarA::" << __func__ << '\n';
//...
}
LibBar::BarA a_;
};
struct ConcreteBarB : BaseB<LibBar> {
LibBar::BarB b_;
};
void
doSomething (IfaceA &a, IfaceB &b)
{
a.doSomethingWith(b);
}
int
main (void)
{
ConcreteFooA foo_a;
ConcreteFooB foo_b;
doSomething(foo_a, foo_b);
ConcreteBarA bar_a;
ConcreteBarB bar_b;
doSomething(bar_a, bar_b);
}