fork download
  1. #include <iostream>
  2. #include <utility>
  3. #include <memory>
  4. #include <vector>
  5. #include <stdexcept>
  6.  
  7. class element
  8. {
  9. public:
  10. element() = default;
  11. virtual ~element() = default;
  12.  
  13. element(std::string value)
  14. : value_{ std::move(value) }
  15. {
  16. }
  17.  
  18. auto value() const -> const std::string&
  19. {
  20. return value_;
  21. }
  22.  
  23. virtual const element& child(std::size_t i) const
  24. {
  25. throw std::runtime_error("Invalid child index.");
  26. }
  27.  
  28. virtual void print(std::ostream& out, int level) const
  29. {
  30. out << std::string(level * 2, ' ')
  31. << "<element>" << value() << "</element>";
  32. }
  33.  
  34. private:
  35. std::string value_;
  36. };
  37.  
  38. auto operator<<(std::ostream& out, const element& e) -> std::ostream&
  39. {
  40. e.print(out, 0);
  41. return out;
  42. }
  43.  
  44. class group : public element
  45. {
  46. public:
  47. template <typename... Children>
  48. group(Children&&... children)
  49. {
  50. append(std::forward<Children>(children)...);
  51. }
  52.  
  53. template <typename... Children>
  54. void append(Children&&... children)
  55. {
  56. (
  57. children_.emplace_back(
  58. std::make_unique<Children>(std::forward<Children>(children))
  59. ),
  60. ...
  61. );
  62. }
  63.  
  64. virtual const element& child(std::size_t i) const override
  65. {
  66. if (i >= children_.size())
  67. throw std::runtime_error("Invalid child index.");
  68. return *children_[i];
  69. }
  70.  
  71. virtual void print(std::ostream& out, int level) const override
  72. {
  73. out << std::string(level * 2, ' ') << "<group>\n";
  74. print_children(out, level + 1);
  75. out << std::string(level * 2, ' ') << "</group>";
  76. }
  77.  
  78. void print_children(std::ostream& out, int level) const
  79. {
  80. for (const auto& child : children_)
  81. {
  82. child->print(out, level);
  83. out << "\n";
  84. }
  85. }
  86.  
  87. private:
  88. std::vector<std::unique_ptr<element>> children_;
  89. };
  90.  
  91. class document : public group
  92. {
  93. public:
  94. template <typename... Children>
  95. document(Children&&... children)
  96. : group{ std::forward<Children>(children)... }
  97. {
  98. }
  99.  
  100. protected:
  101. virtual void print(std::ostream& out, int level) const override
  102. {
  103. out << std::string(level * 2, ' ') << "<document>\n";
  104. print_children(out, level + 1);
  105. out << std::string(level * 2, ' ') << "</document>";
  106. }
  107. };
  108.  
  109. auto main() -> int
  110. {
  111. auto d = document{
  112. group{
  113. element{ "element1" },
  114. element{ "element2" },
  115. element{ "element3" }
  116. },
  117. group{
  118. group{
  119. element{ "element4" },
  120. element{ "element5" },
  121. element{ "element6" }
  122. },
  123. element{ "element7" }
  124. }
  125. };
  126.  
  127. d.append(
  128. group{
  129. element{ "element8" }
  130. }
  131. );
  132.  
  133. std::cout << "\nd --------------------------------------\n\n" << d << "\n";
  134. std::cout << "\nd.child(1) -----------------------------\n\n"
  135. << d.child(1) << "\n";
  136. std::cout << "\nd.child(1).child(0).child(2).value() ---\n\n"
  137. << d.child(1).child(0).child(2).value() << "\n\n";
  138. }
Success #stdin #stdout 0s 4392KB
stdin
Standard input is empty
stdout
d --------------------------------------

<document>
  <group>
    <element>element1</element>
    <element>element2</element>
    <element>element3</element>
  </group>
  <group>
    <group>
      <element>element4</element>
      <element>element5</element>
      <element>element6</element>
    </group>
    <element>element7</element>
  </group>
  <group>
    <element>element8</element>
  </group>
</document>

d.child(1) -----------------------------

<group>
  <group>
    <element>element4</element>
    <element>element5</element>
    <element>element6</element>
  </group>
  <element>element7</element>
</group>

d.child(1).child(0).child(2).value() ---

element6