]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/ptr_container/test/tut1.cpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / ptr_container / test / tut1.cpp
1 //
2 // Boost.Pointer Container
3 //
4 // Copyright Thorsten Ottosen 2003-2005. Use, modification and
5 // distribution is subject to the Boost Software License, Version
6 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
8 //
9 // For more information, see http://www.boost.org/libs/ptr_container/
10 //
11
12 //
13 // This example is intended to get you started.
14 // Notice how the smart container
15 //
16 // 1. takes ownership of objects
17 // 2. transfers ownership
18 // 3. applies indirection to iterators
19 // 4. clones objects from other smart containers
20 //
21
22 //
23 // First we select which container to use.
24 //
25 #include <boost/ptr_container/ptr_deque.hpp>
26
27 //
28 // we need these later in the example
29 //
30 #include <boost/assert.hpp>
31 #include <string>
32 #include <exception>
33
34
35 //
36 // Then we define a small polymorphic class
37 // hierarchy.
38 //
39
40 class animal : boost::noncopyable
41 {
42 virtual std::string do_speak() const = 0;
43 std::string name_;
44
45 protected:
46 //
47 // Animals cannot be copied...
48 //
49 animal( const animal& r ) : name_( r.name_ ) { }
50 void operator=( const animal& );
51
52 private:
53 //
54 // ...but due to advances in genetics, we can clone them!
55 //
56
57 virtual animal* do_clone() const = 0;
58
59 public:
60 animal( const std::string& name ) : name_(name) { }
61 virtual ~animal() throw() { }
62
63 std::string speak() const
64 {
65 return do_speak();
66 }
67
68 std::string name() const
69 {
70 return name_;
71 }
72
73 animal* clone() const
74 {
75 return do_clone();
76 }
77 };
78
79 //
80 // An animal is still not Clonable. We need this last hook.
81 //
82 // Notice that we pass the animal by const reference
83 // and return by pointer.
84 //
85
86 animal* new_clone( const animal& a )
87 {
88 return a.clone();
89 }
90
91 //
92 // We do not need to define 'delete_clone()' since
93 // since the default is to call the default 'operator delete()'.
94 //
95
96 const std::string muuuh = "Muuuh!";
97 const std::string oiink = "Oiiink";
98
99 class cow : public animal
100 {
101 virtual std::string do_speak() const
102 {
103 return muuuh;
104 }
105
106 virtual animal* do_clone() const
107 {
108 return new cow( *this );
109 }
110
111 public:
112 cow( const std::string& name ) : animal(name) { }
113 };
114
115 class pig : public animal
116 {
117 virtual std::string do_speak() const
118 {
119 return oiink;
120 }
121
122 virtual animal* do_clone() const
123 {
124 return new pig( *this );
125 }
126
127 public:
128 pig( const std::string& name ) : animal(name) { }
129 };
130
131 //
132 // Then we, of course, need a place to put all
133 // those animals.
134 //
135
136 class farm
137 {
138 //
139 // This is where the smart containers are handy
140 //
141 typedef boost::ptr_deque<animal> barn_type;
142 barn_type barn;
143
144 //
145 // An error type
146 //
147 struct farm_trouble : public std::exception { };
148
149 public:
150 //
151 // We would like to make it possible to
152 // iterate over the animals in the farm
153 //
154 typedef barn_type::iterator animal_iterator;
155
156 //
157 // We also need to count the farm's size...
158 //
159 typedef barn_type::size_type size_type;
160
161 //
162 // And we also want to transfer an animal
163 // safely around. The easiest way to think
164 // about '::auto_type' is to imagine a simplified
165 // 'std::auto_ptr<T>' ... this means you can expect
166 //
167 // T* operator->()
168 // T* release()
169 // deleting destructor
170 //
171 // but not more.
172 //
173 typedef barn_type::auto_type animal_transport;
174
175 //
176 // Create an empty farm.
177 //
178 farm() { }
179
180 //
181 // We need a constructor that can make a new
182 // farm by cloning a range of animals.
183 //
184 farm( animal_iterator begin, animal_iterator end )
185 :
186 //
187 // Objects are always cloned before insertion
188 // unless we explicitly add a pointer or
189 // use 'release()'. Therefore we actually
190 // clone all animals in the range
191 //
192 barn( begin, end ) { }
193
194 //
195 // ... so we need some other function too
196 //
197
198 animal_iterator begin()
199 {
200 return barn.begin();
201 }
202
203 animal_iterator end()
204 {
205 return barn.end();
206 }
207
208 //
209 // Here it is quite ok to have an 'animal*' argument.
210 // The smart container will handle all ownership
211 // issues.
212 //
213 void buy_animal( animal* a )
214 {
215 barn.push_back( a );
216 }
217
218 //
219 // The farm can also be in economical trouble and
220 // therefore be in the need to sell animals.
221 //
222 animal_transport sell_animal( animal_iterator to_sell )
223 {
224 if( to_sell == end() )
225 throw farm_trouble();
226
227 //
228 // Here we remove the animal from the barn,
229 // but the animal is not deleted yet...it's
230 // up to the buyer to decide what
231 // to do with it.
232 //
233 return barn.release( to_sell );
234 }
235
236 //
237 // How big a farm do we have?
238 //
239 size_type size() const
240 {
241 return barn.size();
242 }
243
244 //
245 // If things are bad, we might choose to sell all animals :-(
246 //
247 std::auto_ptr<barn_type> sell_farm()
248 {
249 return barn.release();
250 }
251
252 //
253 // However, if things are good, we might buy somebody
254 // else's farm :-)
255 //
256
257 void buy_farm( std::auto_ptr<barn_type> other )
258 {
259 //
260 // This line inserts all the animals from 'other'
261 // and is guaranteed either to succeed or to have no
262 // effect
263 //
264 barn.transfer( barn.end(), // insert new animals at the end
265 *other ); // we want to transfer all animals,
266 // so we use the whole container as argument
267 //
268 // You might think you would have to do
269 //
270 // other.release();
271 //
272 // but '*other' is empty and can go out of scope as it wants
273 //
274 BOOST_ASSERT( other->empty() );
275 }
276
277 }; // class 'farm'.
278
279 int main()
280 {
281 //
282 // First we make a farm
283 //
284 farm animal_farm;
285 BOOST_ASSERT( animal_farm.size() == 0u );
286
287 animal_farm.buy_animal( new pig("Betty") );
288 animal_farm.buy_animal( new pig("Benny") );
289 animal_farm.buy_animal( new pig("Jeltzin") );
290 animal_farm.buy_animal( new cow("Hanz") );
291 animal_farm.buy_animal( new cow("Mary") );
292 animal_farm.buy_animal( new cow("Frederik") );
293 BOOST_ASSERT( animal_farm.size() == 6u );
294
295 //
296 // Then we make another farm...it will actually contain
297 // a clone of the other farm.
298 //
299 farm new_farm( animal_farm.begin(), animal_farm.end() );
300 BOOST_ASSERT( new_farm.size() == 6u );
301
302 //
303 // Is it really clones in the new farm?
304 //
305 BOOST_ASSERT( new_farm.begin()->name() == "Betty" );
306
307 //
308 // Then we search for an animal, Mary (the Crown Princess of Denmark),
309 // because we would like to buy her ...
310 //
311 typedef farm::animal_iterator iterator;
312 iterator to_sell;
313 for( iterator i = animal_farm.begin(),
314 end = animal_farm.end();
315 i != end; ++i )
316 {
317 if( i->name() == "Mary" )
318 {
319 to_sell = i;
320 break;
321 }
322 }
323
324 farm::animal_transport mary = animal_farm.sell_animal( to_sell );
325
326
327 if( mary->speak() == muuuh )
328 //
329 // Great, Mary is a cow, and she may live longer
330 //
331 new_farm.buy_animal( mary.release() );
332 else
333 //
334 // Then the animal would be destroyed (!)
335 // when we go out of scope.
336 //
337 ;
338
339 //
340 // Now we can observe some changes to the two farms...
341 //
342 BOOST_ASSERT( animal_farm.size() == 5u );
343 BOOST_ASSERT( new_farm.size() == 7u );
344
345 //
346 // The new farm has however underestimated how much
347 // it cost to feed Mary and its owner is forced to sell the farm...
348 //
349 animal_farm.buy_farm( new_farm.sell_farm() );
350
351 BOOST_ASSERT( new_farm.size() == 0u );
352 BOOST_ASSERT( animal_farm.size() == 12u );
353 }