fork download
  1. #include <iostream>
  2. #include <memory>
  3.  
  4. template<typename T>
  5. struct A {
  6. T value_;
  7.  
  8. A(T value) : value_(value) {}
  9.  
  10. void sayHello() const {
  11. std::cout << "Hello from A! " << value_ << '\n';
  12. }
  13. };
  14. template<typename T>
  15. struct B {
  16. T value_;
  17.  
  18. B(T value) : value_(value) {}
  19.  
  20. void sayHello() const {
  21. std::cout << "Hello from B! " << value_ << '\n';
  22. }
  23. };
  24.  
  25. class Wrapper {
  26. private:
  27. class Concept {
  28. public:
  29. virtual ~Concept() = default;
  30.  
  31. virtual void sayHello() const = 0;
  32. };
  33.  
  34. template<typename T>
  35. class Model final
  36. : public Concept {
  37. private:
  38. T data_;
  39.  
  40. public:
  41. Model(T data) : data_(data) {}
  42.  
  43. virtual void sayHello() const override {
  44. data_.sayHello();
  45. }
  46.  
  47. private:
  48. template<typename U>
  49. friend inline void doSomething(const Concept &lhs, const B<U> &rhs) {
  50. T x = static_cast<const Model<T> &>(lhs).data_;
  51.  
  52. x.sayHello();
  53. rhs.sayHello();
  54.  
  55. auto y = x.value_ + rhs.value_;
  56.  
  57. std::cout << y << '\n';
  58. }
  59. };
  60.  
  61. template<typename U>
  62. friend inline void doSomething(const Concept &lhs, const B<U> &rhs);
  63.  
  64. std::shared_ptr<const Concept> ptr_;
  65.  
  66. public:
  67. template<typename T>
  68. explicit inline Wrapper(T a)
  69. : ptr_(std::make_shared<Model<A<T>>>(std::move(a))) {}
  70.  
  71. template<typename U>
  72. friend inline void someFriend(Wrapper &lhs, B<U> &rhs) {
  73. doSomething(*lhs.ptr_, rhs);
  74. }
  75. };
  76.  
  77. int main() {
  78. Wrapper a(1);
  79. B<int> b{2};
  80.  
  81. someFriend(a, b);
  82.  
  83. return 0;
  84. }
Success #stdin #stdout 0s 15240KB
stdin
Standard input is empty
stdout
Hello from A! 1
Hello from B! 2
3