tut1.cpp 8.1 KB

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