fork download
  1. #include <utility>
  2. #include <cstddef>
  3. #include <iostream>
  4.  
  5. using namespace std;
  6.  
  7. struct Triangle;
  8. struct Square;
  9.  
  10. struct PolygonVisitor
  11. {
  12. virtual ~PolygonVisitor() {}
  13.  
  14. virtual void visit(Triangle& tr) = 0;
  15. virtual void visit(Square& sq) = 0;
  16. };
  17.  
  18. struct Polygon
  19. {
  20. virtual void accept(PolygonVisitor& v) = 0;
  21. };
  22.  
  23. struct Triangle : Polygon
  24. {
  25. void accept(PolygonVisitor& v) override
  26. {
  27. v.visit(*this);
  28. }
  29. };
  30.  
  31. struct Square : Polygon
  32. {
  33. void accept(PolygonVisitor& v) override
  34. {
  35. v.visit(*this);
  36. }
  37. };
  38.  
  39. template <typename T,
  40. typename F,
  41. typename BaseInner,
  42. typename ArgsT>
  43. struct ComposeVisitor
  44. {
  45. struct Inner : public BaseInner
  46. {
  47. using BaseInner::visit;
  48. Inner(ArgsT&& args) :
  49. BaseInner(move(args.second)),
  50. m_f(move(args.first))
  51. {
  52. }
  53. void visit(T& t) final override
  54. {
  55. m_f(t);
  56. }
  57. private:
  58. F m_f;
  59. };
  60. ComposeVisitor(ArgsT&& args) :
  61. m_args(move(args))
  62. {
  63. }
  64. template <typename Tadd,
  65. typename Fadd>
  66. ComposeVisitor <
  67. Tadd,
  68. Fadd,
  69. Inner,
  70. pair < Fadd, ArgsT >> on(Fadd&& f)
  71. {
  72. return ComposeVisitor <
  73. Tadd,
  74. Fadd,
  75. Inner,
  76. pair < Fadd, ArgsT >> (
  77. make_pair(
  78. move(f),
  79. move(m_args)));
  80. }
  81. Inner end_visitor()
  82. {
  83. return Inner(move(m_args));
  84. }
  85.  
  86. ArgsT m_args;
  87. };
  88. template <typename TVisitorBase>
  89. struct EmptyVisitor
  90. {
  91. struct Inner : public TVisitorBase
  92. {
  93. using TVisitorBase::visit;
  94. Inner(nullptr_t) {}
  95. };
  96.  
  97. template <typename Tadd, typename Fadd>
  98. ComposeVisitor <
  99. Tadd,
  100. Fadd,
  101. Inner,
  102. pair < Fadd, nullptr_t >> on(Fadd&& f)
  103. {
  104. return ComposeVisitor <
  105. Tadd,
  106. Fadd,
  107. Inner,
  108. pair < Fadd, nullptr_t >> (
  109. make_pair(
  110. move(f),
  111. nullptr));
  112. }
  113. };
  114. template <typename TVisitorBase>
  115. EmptyVisitor<TVisitorBase> begin_visitor()
  116. {
  117. return EmptyVisitor<TVisitorBase>();
  118. }
  119.  
  120. int main()
  121. {
  122. int sides = 0;
  123.  
  124. auto v = begin_visitor<PolygonVisitor>()
  125. .on<Triangle>([&sides](Triangle&)
  126. {
  127. sides = 3;
  128. })
  129. .on<Square>([&sides](Square&)
  130. {
  131. sides = 4;
  132. })
  133. .end_visitor();
  134.  
  135. Triangle p;
  136. p.accept(v);
  137.  
  138. std::cout << "sides: " << sides << std::endl;
  139. }
  140.  
Compilation error #stdin compilation error #stdout 0s 0KB
stdin
Standard input is empty
compilation info
prog.cpp: In instantiation of ‘struct ComposeVisitor<Triangle, main()::__lambda0, EmptyVisitor<PolygonVisitor>::Inner, std::pair<main()::__lambda0, std::nullptr_t> >::Inner’:
prog.cpp:45:12:   required from ‘struct ComposeVisitor<Square, main()::__lambda1, ComposeVisitor<Triangle, main()::__lambda0, EmptyVisitor<PolygonVisitor>::Inner, std::pair<main()::__lambda0, std::nullptr_t> >::Inner, std::pair<main()::__lambda1, std::pair<main()::__lambda0, std::nullptr_t> > >::Inner’
prog.cpp:133:22:   required from here
prog.cpp:81:11: error: cannot allocate an object of abstract type ‘ComposeVisitor<Triangle, main()::__lambda0, EmptyVisitor<PolygonVisitor>::Inner, std::pair<main()::__lambda0, std::nullptr_t> >::Inner’
     Inner end_visitor()
           ^
prog.cpp:45:12: note:   because the following virtual functions are pure within ‘ComposeVisitor<Triangle, main()::__lambda0, EmptyVisitor<PolygonVisitor>::Inner, std::pair<main()::__lambda0, std::nullptr_t> >::Inner’:
     struct Inner : public BaseInner
            ^
prog.cpp:15:18: note: 	virtual void PolygonVisitor::visit(Square&)
     virtual void visit(Square& sq) = 0;
                  ^
stdout
Standard output is empty