fork download
  1. #include <iostream>
  2. #include <cassert>
  3.  
  4. class LibFoo;
  5. class LibBar;
  6.  
  7. class IfaceA;
  8. class IfaceB;
  9.  
  10. template <typename LIB> class BaseA;
  11. template <typename LIB> class BaseB;
  12.  
  13. struct IfaceA
  14. {
  15. virtual ~IfaceA () {}
  16. virtual operator BaseA<LibFoo> * () { return 0; }
  17. virtual operator BaseA<LibBar> * () { return 0; }
  18. virtual void doSomethingWith (IfaceB &) = 0;
  19. };
  20.  
  21. struct IfaceB {
  22. virtual ~IfaceB () {}
  23. virtual operator BaseB<LibFoo> * () { return 0; }
  24. virtual operator BaseB<LibBar> * () { return 0; }
  25. };
  26.  
  27. template <typename LIB>
  28. struct BaseA : IfaceA {
  29. operator BaseA * () override { return this; }
  30.  
  31. void doSomethingWith (IfaceB &b) override {
  32. doSomethingWithB(b);
  33. }
  34.  
  35. void doSomethingWithB (BaseB<LIB> *b) {
  36. assert(b);
  37. doSomethingWithB(*b);
  38. }
  39.  
  40. virtual void doSomethingWithB (BaseB<LIB> &b) = 0;
  41. };
  42.  
  43. template <typename LIB>
  44. struct BaseB : IfaceB {
  45. operator BaseB * () override { return this; }
  46. };
  47.  
  48. struct LibFoo {
  49. class FooA {};
  50. class FooB {};
  51. };
  52.  
  53. struct ConcreteFooA : BaseA<LibFoo> {
  54. void doSomethingWithB (BaseB<LibFoo> &) override {
  55. std::cout << "ConcreteFooA::" << __func__ << '\n';
  56. //...
  57. }
  58.  
  59. LibFoo::FooA a_;
  60. };
  61.  
  62. struct ConcreteFooB : BaseB<LibFoo> {
  63. LibFoo::FooB b_;
  64. };
  65.  
  66. struct LibBar {
  67. class BarA {};
  68. class BarB {};
  69. };
  70.  
  71. struct ConcreteBarA : BaseA<LibBar> {
  72. void doSomethingWithB (BaseB<LibBar> &) override {
  73. std::cout << "ConcreteBarA::" << __func__ << '\n';
  74. //...
  75. }
  76.  
  77. LibBar::BarA a_;
  78. };
  79.  
  80. struct ConcreteBarB : BaseB<LibBar> {
  81. LibBar::BarB b_;
  82. };
  83.  
  84. void
  85. doSomething (IfaceA &a, IfaceB &b)
  86. {
  87. a.doSomethingWith(b);
  88. }
  89.  
  90. int
  91. main (void)
  92. {
  93. ConcreteFooA foo_a;
  94. ConcreteFooB foo_b;
  95.  
  96. doSomething(foo_a, foo_b);
  97.  
  98. ConcreteBarA bar_a;
  99. ConcreteBarB bar_b;
  100.  
  101. doSomething(bar_a, bar_b);
  102. }
Success #stdin #stdout 0s 3300KB
stdin
Standard input is empty
stdout
ConcreteFooA::doSomethingWithB
ConcreteBarA::doSomethingWithB