1
+ #include < memory>
2
+ #include < vector>
3
+ #include < deque>
4
+ #include < string>
5
+ #include < iostream>
6
+
7
+ class IGraphic
8
+ {
9
+ public:
10
+ virtual auto type () const -> const std::string = 0;
11
+ virtual auto draw () -> void = 0;
12
+ virtual auto rotate (double ) -> void = 0;
13
+ virtual ~IGraphic () = default ;
14
+ };
15
+
16
+ using cstring = const char *;
17
+ using GNode = std::shared_ptr<IGraphic>;
18
+
19
+ class Group : public IGraphic
20
+ {
21
+ private:
22
+ std::vector<GNode> _nodes;
23
+ std::string _id;
24
+ static constexpr cstring _type = " Group" ;
25
+
26
+ public:
27
+ Group (const std::string &id) : _id(id)
28
+ {
29
+ std::cout << " [TRACE] Create group = " << id << " \n " ;
30
+ }
31
+ ~Group ()
32
+ {
33
+ std::cout << " [TRACE] Destroy group - id = << " << _id << " \n " ;
34
+ }
35
+
36
+ auto begin () const -> decltype(_nodes.begin())
37
+ {
38
+ return _nodes.begin ();
39
+ }
40
+ auto end () const -> decltype(_nodes.end())
41
+ {
42
+ return _nodes.end ();
43
+ }
44
+
45
+ auto clear () -> void
46
+ {
47
+ _nodes.clear ();
48
+ }
49
+ auto size () -> size_t
50
+ {
51
+ return _nodes.size ();
52
+ }
53
+ auto add (GNode n) -> void
54
+ {
55
+ std::cout << " [TRACE] id = " << _id
56
+ << " ; Add object = " << n->type () << " \n " ;
57
+ _nodes.push_back (n);
58
+ }
59
+ auto add (IGraphic *n) -> void
60
+ {
61
+ std::cout << " [TRACE] id = " << _id
62
+ << " ; Add object = " << n->type () << " \n " ;
63
+ _nodes.push_back (std::shared_ptr<IGraphic>(n));
64
+ }
65
+ // Add stack-allocated object
66
+ auto addFromStack (IGraphic *n) -> void
67
+ {
68
+ std::cout << " [TRACE] id = " << _id
69
+ << " ; Add object = " << n->type () << " \n " ;
70
+ // Dummy deleter to avoid core dump by avoiding deleting
71
+ // stack-allocated object or non-owned pointer.
72
+ auto s = std::shared_ptr<IGraphic>(n, [](IGraphic *) { return ; });
73
+ _nodes.push_back (s);
74
+ }
75
+
76
+ // Note: Template methods should always be in the header files
77
+ template <class Node >
78
+ auto addNew (const std::string &id) -> void
79
+ {
80
+ auto n = std::make_unique<Node>(id);
81
+ std::cout << " [TRACE] id = " << _id
82
+ << " ; Add object = " << n->type () << " \n " ;
83
+ _nodes.push_back (std::move (n));
84
+ }
85
+
86
+ // ======> Interface IGraphic <<=========//
87
+
88
+ auto type () const -> const std::string override
89
+ {
90
+ return _type;
91
+ }
92
+ auto draw () -> void override
93
+ {
94
+ std::cout << " [TRACE] Draw group - id = " << _id << " \n " ;
95
+ for (const auto &obj : _nodes)
96
+ obj->draw ();
97
+ }
98
+ auto rotate (double angle) -> void override
99
+ {
100
+ std::cout << " [TRACE] Rotate group - id = " << _id << " \n " ;
101
+ for (const auto &obj : _nodes)
102
+ obj->rotate (angle);
103
+ }
104
+ };
105
+
106
+ class Line : public IGraphic
107
+ {
108
+ private:
109
+ static constexpr cstring _type = " Line" ;
110
+ std::string _id;
111
+
112
+ public:
113
+ Line (const std::string &id) : _id{id} {}
114
+ auto type () const -> const std::string override
115
+ {
116
+ return _type;
117
+ }
118
+ auto draw () -> void override
119
+ {
120
+ std::cout << " [TRACE] Draw line - id = " << _id << " \n " ;
121
+ }
122
+ auto rotate (double angle) -> void override
123
+ {
124
+ std::cout << " [TRACE] Rotate line ; id = " << _id
125
+ << " ; angle = " << angle << " \n " ;
126
+ }
127
+ };
128
+
129
+ class Triangle : public IGraphic
130
+ {
131
+ private:
132
+ static constexpr cstring _type = " Triangle" ;
133
+ std::string _id;
134
+
135
+ public:
136
+ Triangle (const std::string &id) : _id{id} {}
137
+ auto type () const -> const std::string override
138
+ {
139
+ return _type;
140
+ }
141
+ auto draw () -> void override
142
+ {
143
+ std::cout << " [TRACE] Draw triangle - id = " << _id << " \n " ;
144
+ }
145
+ auto rotate (double angle) -> void override
146
+ {
147
+ std::cout << " [TRACE] Rotate triangle"
148
+ << " id = " << _id
149
+ << " angle = " << angle << " \n " ;
150
+ }
151
+ };
152
+
153
+ // Count total number of elements
154
+ auto countElements (const Group &group) -> size_t
155
+ {
156
+ size_t n = 0 ;
157
+ for (const auto &g : group)
158
+ {
159
+ if (g->type () == " Group" )
160
+ {
161
+ auto p = static_cast <Group *>(g.get ());
162
+ n += countElements (*p);
163
+ }
164
+ else
165
+ {
166
+ ++n;
167
+ }
168
+ }
169
+ return n;
170
+ }
171
+
172
+ int main ()
173
+ {
174
+ const char nl = ' \n ' ;
175
+
176
+ std::cout << " === Objects construction === " << nl;
177
+
178
+ auto groupA = Group (" groupA" );
179
+ groupA.add (new Triangle (" triangleA1" ));
180
+ groupA.add (new Line (" lineA1" ));
181
+ groupA.addNew <Line>(" LineA2" );
182
+
183
+ auto groupB = std::make_shared<Group>(" GroupB" );
184
+ groupB->add (new Triangle (" triangleB1" ));
185
+ groupB->addNew <Triangle>(" triangleB2" );
186
+ groupB->addNew <Line>(" LineB1" );
187
+ groupB->addNew <Line>(" LineB2" );
188
+ auto triangleB3 = Triangle (" triangleB3" );
189
+ groupB->addFromStack (&triangleB3);
190
+ groupA.add (groupB);
191
+
192
+ std::cout << nl << " === End of object construction === " << nl;
193
+ std::cout << " Total of elements of groupA = " << countElements (groupA) << " \n " ;
194
+ std::cout << " Total of elements of groupB = " << countElements (*groupB) << " \n " ;
195
+
196
+ std::cout << nl << " [*] ==> Draw group B"
197
+ << " \n " ;
198
+ groupB->draw ();
199
+
200
+ std::cout << nl << " [*] ==> Rotate group B"
201
+ << " \n " ;
202
+ groupB->rotate (90 );
203
+
204
+ std::cout << nl << " [*] ==> Draw group A"
205
+ << " \n " ;
206
+ groupA.draw ();
207
+
208
+ std::cout << nl << " [*] ==> Rotate group A"
209
+ << " \n " ;
210
+ groupA.rotate (15 );
211
+
212
+ std::cout << nl << " [*] ==> Remove objects from group B"
213
+ << " \n " ;
214
+ groupB->clear ();
215
+ groupA.draw ();
216
+
217
+ std::cout << " === End of Program ===="
218
+ << " \n " ;
219
+
220
+ return 0 ;
221
+ }
0 commit comments