ptr_map.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  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. #include "test_data.hpp"
  12. #include <boost/test/unit_test.hpp>
  13. #include <boost/ptr_container/exception.hpp>
  14. #include <boost/ptr_container/detail/ptr_container_disable_deprecated.hpp>
  15. #include <boost/range/sub_range.hpp>
  16. #include <boost/cast.hpp>
  17. #include <cstdlib>
  18. #include <iostream>
  19. #include <memory>
  20. #include <string>
  21. //
  22. // abstract base class definition
  23. //
  24. struct abstract_base
  25. {
  26. virtual ~abstract_base() {}
  27. virtual void foo() = 0;
  28. virtual abstract_base* clone() const = 0;
  29. };
  30. struct implementation : abstract_base
  31. {
  32. implementation()
  33. { }
  34. implementation( const implementation& )
  35. { }
  36. implementation( int, std::string, int, std::string )
  37. { }
  38. virtual void foo() {}
  39. virtual abstract_base* clone() const
  40. {
  41. return new implementation( *this );
  42. }
  43. };
  44. inline std::ostream& operator<<( std::ostream& out, const abstract_base& r )
  45. {
  46. return out;
  47. }
  48. inline abstract_base* new_clone( const abstract_base& r )
  49. {
  50. return r.clone();
  51. }
  52. //
  53. // ptr_map test
  54. //
  55. template< typename C, typename B, typename T >
  56. void ptr_map_test();
  57. template< class Key >
  58. Key get_next_key( const Key& k );
  59. template<>
  60. int get_next_key<int>( const int& )
  61. {
  62. return rand();
  63. }
  64. template<>
  65. std::string get_next_key<std::string>( const std::string& )
  66. {
  67. return boost::lexical_cast<std::string>( rand() );
  68. }
  69. #if defined(BOOST_PTR_CONTAINER_DISABLE_DEPRECATED)
  70. #pragma GCC diagnostic push
  71. #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
  72. #endif
  73. template< typename C, typename B, typename T >
  74. void ptr_map_test()
  75. {
  76. using namespace boost;
  77. BOOST_TEST_MESSAGE( "starting associative container test" );
  78. enum { max_cnt = 10, size = 100 };
  79. C c;
  80. BOOST_CHECK( c.size() == 0 );
  81. const C c2( c.begin(), c.end() );
  82. BOOST_CHECK( c.size() == c2.size() );
  83. C c3;
  84. BOOST_TEST_MESSAGE( "finished construction test" );
  85. BOOST_DEDUCED_TYPENAME C::allocator_type alloc = c.get_allocator();
  86. BOOST_DEDUCED_TYPENAME C::iterator i = c.begin();
  87. BOOST_DEDUCED_TYPENAME C::const_iterator ci = c2.begin();
  88. BOOST_DEDUCED_TYPENAME C::iterator i2 = c.end();
  89. hide_warning(i2);
  90. BOOST_DEDUCED_TYPENAME C::const_iterator ci2 = c2.begin();
  91. hide_warning(ci2);
  92. BOOST_DEDUCED_TYPENAME C::reverse_iterator ri = c.rbegin();
  93. hide_warning(ri);
  94. BOOST_DEDUCED_TYPENAME C::const_reverse_iterator cri = c2.rbegin();
  95. hide_warning(cri);
  96. BOOST_DEDUCED_TYPENAME C::reverse_iterator rv2 = c.rend();
  97. hide_warning(rv2);
  98. BOOST_DEDUCED_TYPENAME C::const_reverse_iterator cvr2 = c2.rend();
  99. hide_warning(cvr2);
  100. BOOST_DEDUCED_TYPENAME C::key_type a_key;
  101. BOOST_TEST_MESSAGE( "finished iterator test" );
  102. BOOST_DEDUCED_TYPENAME C::size_type s = c.size();
  103. BOOST_DEDUCED_TYPENAME C::size_type s2 = c.max_size();
  104. hide_warning(s2);
  105. BOOST_CHECK_EQUAL( c.size(), s );
  106. bool b = c.empty();
  107. hide_warning(b);
  108. BOOST_TEST_MESSAGE( "finished accessors test" );
  109. a_key = get_next_key( a_key );
  110. c.insert( a_key, new T );
  111. a_key = get_next_key( a_key );
  112. c.insert( a_key, new T );
  113. c3.insert( c.begin(), c.end() );
  114. c.insert( c3 );
  115. c.erase( c.begin() );
  116. BOOST_CHECK( c3.end() == c3.erase( boost::make_iterator_range(c3) ) );
  117. c3.erase( a_key );
  118. BOOST_CHECK( c3.empty() );
  119. c.swap( c3 );
  120. swap(c,c3);
  121. swap(c3,c);
  122. BOOST_CHECK( !c3.empty() );
  123. c3.clear();
  124. BOOST_CHECK( c3.empty() );
  125. BOOST_TEST_MESSAGE( "finished modifiers test" );
  126. a_key = get_next_key( a_key );
  127. c.insert( a_key, new T );
  128. a_key = get_next_key( a_key );
  129. #ifndef BOOST_NO_AUTO_PTR
  130. c.insert( a_key, std::auto_ptr<T>( new T ) );
  131. #endif
  132. #ifndef BOOST_NO_CXX11_SMART_PTR
  133. c.insert( a_key, std::unique_ptr<T>( new T ) );
  134. #endif
  135. typename C::auto_type ptr2 = c.release( c.begin() );
  136. #ifndef BOOST_NO_AUTO_PTR
  137. std::auto_ptr<C> ap = c.release();
  138. #else
  139. std::unique_ptr<C> up = c.release();
  140. #endif
  141. c = c2.clone();
  142. BOOST_TEST_MESSAGE( "finished release/clone test" );
  143. a_key = get_next_key( a_key );
  144. c3.insert( a_key, new T );
  145. a_key = get_next_key( a_key );
  146. c3.insert( a_key, new T );
  147. c. BOOST_NESTED_TEMPLATE transfer<C>( c3.begin(), c3 );
  148. c. BOOST_NESTED_TEMPLATE transfer<C>( c3.begin(), c3.end(), c3 );
  149. BOOST_CHECK( c3.empty() );
  150. BOOST_CHECK( !c.empty() );
  151. c3. BOOST_NESTED_TEMPLATE transfer<C>( c );
  152. BOOST_CHECK( !c3.empty() );
  153. BOOST_CHECK( c.empty() );
  154. #ifdef BOOST_NO_SFINAE
  155. #else
  156. c. BOOST_NESTED_TEMPLATE transfer<C>( make_iterator_range(c3), c3 );
  157. BOOST_CHECK( !c.empty() );
  158. BOOST_CHECK( c3.empty() );
  159. c3. BOOST_NESTED_TEMPLATE transfer<C>(c);
  160. #endif
  161. BOOST_TEST_MESSAGE( "finished transfer test" );
  162. BOOST_CHECK( !c3.empty() );
  163. c3.replace( c3.begin(), new T );
  164. #ifndef BOOST_NO_AUTO_PTR
  165. c3.replace( c3.begin(), std::auto_ptr<T>( new T ) );
  166. #endif
  167. #ifndef BOOST_NO_CXX11_SMART_PTR
  168. c3.replace( c3.begin(), std::unique_ptr<T>( new T ) );
  169. #endif
  170. BOOST_TEST_MESSAGE( "finished set/map interface test" );
  171. // @todo: make macro with algorithms so that the right erase() is called.
  172. // c.unique();
  173. // c.unique( std::not_equal_to<T>() );
  174. // c.remove( T() );
  175. // c.remove_if( std::binder1st< std::equal_to<T> >( T() ) );
  176. sub_range<C> sub;
  177. sub_range<const C> csub;
  178. i = c.find( get_next_key( a_key ) );
  179. ci = c2.find( get_next_key( a_key ) );
  180. BOOST_CHECK_EQUAL(0, c2.count( get_next_key( a_key ) ));
  181. i = c.lower_bound( get_next_key( a_key ) );
  182. ci = c2.lower_bound( get_next_key( a_key ) );
  183. i = c.upper_bound( get_next_key( a_key ) );
  184. ci = c2.upper_bound( get_next_key( a_key ) );
  185. sub = c.equal_range( get_next_key( a_key ) );
  186. csub = c2.equal_range( get_next_key( a_key ) );
  187. try
  188. {
  189. c.at( get_next_key( a_key ) );
  190. }
  191. catch( const bad_ptr_container_operation& )
  192. { }
  193. try
  194. {
  195. c2.at( get_next_key( a_key ) );
  196. }
  197. catch( const bad_ptr_container_operation& )
  198. { }
  199. BOOST_TEST_MESSAGE( "finished algorithms interface test" );
  200. typename C::iterator it = c.begin(), e = c.end();
  201. for( ; it != e; ++it )
  202. {
  203. std::cout << "\n mapped value = " << *it->second << " key = " << it->first;
  204. //std::cout << "\n mapped value = " << it.value() << " key = " << it.key();
  205. }
  206. typename C::reverse_iterator rit = c.rbegin(), re = c.rend();
  207. for( ; rit != re; ++rit )
  208. {
  209. std::cout << "\n mapped value = " << *rit->second << " key = " << rit->first;
  210. //std::cout << "\n mapped value = " << rit.value() << " key = " << rit.key();
  211. //std::cout << "\n mapped value (base) = "
  212. // << rit.base().value() << " key = " << rit.base().key();
  213. }
  214. typename C::const_reverse_iterator crit = c2.rbegin(), cre = c2.rend();
  215. for( ; crit != cre; ++crit )
  216. {
  217. std::cout << "\n mapped value = " << *(*crit).second << " key = " << (*crit).first;
  218. //std::cout << "\n mapped value = " << crit.value() << " key = " << crit.key();
  219. //std::cout << "\n mapped value (base) = "
  220. // << crit.base().value() << " key = " << crit.base().key();
  221. }
  222. BOOST_TEST_MESSAGE( "finished iterator test" );
  223. a_key = get_next_key( a_key );
  224. c.insert( a_key, new T );
  225. c.erase( a_key );
  226. c.erase( a_key );
  227. }
  228. #if defined(BOOST_PTR_CONTAINER_DISABLE_DEPRECATED)
  229. #pragma GCC diagnostic pop
  230. #endif
  231. template< class CDerived, class CBase, class T >
  232. void test_transfer()
  233. {
  234. CDerived from;
  235. CBase to;
  236. int key = get_next_key( key );
  237. from.insert( key, new T );
  238. key = get_next_key( key );
  239. from.insert( key, new T );
  240. transfer_test( from, to );
  241. }
  242. template< class BaseContainer, class DerivedContainer, class Derived >
  243. void map_container_assignment_test()
  244. {
  245. DerivedContainer derived;
  246. std::string foo( "foo" );
  247. std::string bar( "foo" );
  248. derived.insert( foo, new Derived );
  249. derived.insert( bar, new Derived );
  250. BaseContainer base_container( derived );
  251. BOOST_CHECK_EQUAL( derived.size(), base_container.size() );
  252. base_container.clear();
  253. base_container = derived;
  254. BOOST_CHECK_EQUAL( derived.size(), base_container.size() );
  255. BaseContainer base2( base_container );
  256. BOOST_CHECK_EQUAL( base2.size(), base_container.size() );
  257. base2 = base_container;
  258. BOOST_CHECK_EQUAL( base2.size(), base_container.size() );
  259. base_container = base_container;
  260. }
  261. #include <boost/ptr_container/ptr_map.hpp>
  262. using namespace std;
  263. void test_map()
  264. {
  265. ptr_map_test< ptr_map<int, Base>, Base, Derived_class >();
  266. ptr_map_test< ptr_map<int, Value>, Value, Value >();
  267. ptr_map_test< ptr_map<int, nullable<Base> >, Base, Derived_class >();
  268. ptr_map_test< ptr_map<int, nullable<Value> >, Value, Value >();
  269. ptr_map_test< ptr_map<int, abstract_base>, abstract_base, implementation >();
  270. ptr_map_test< ptr_multimap<int,Base>, Base, Derived_class >();
  271. ptr_map_test< ptr_multimap<int,Value>, Value, Value >();
  272. ptr_map_test< ptr_multimap<int, nullable<Base> >, Base, Derived_class >();
  273. ptr_map_test< ptr_multimap<int, nullable<Value> >, Value, Value >();
  274. map_container_assignment_test< ptr_map<std::string,Base>,
  275. ptr_map<std::string,Derived_class>,
  276. Derived_class>();
  277. map_container_assignment_test< ptr_map<std::string, nullable<Base> >,
  278. ptr_map<std::string,Derived_class>,
  279. Derived_class>();
  280. map_container_assignment_test< ptr_map<std::string, nullable<Base> >,
  281. ptr_map<std::string, nullable<Derived_class> >,
  282. Derived_class>();
  283. map_container_assignment_test< ptr_multimap<std::string,Base>,
  284. ptr_multimap<std::string,Derived_class>,
  285. Derived_class>();
  286. map_container_assignment_test< ptr_multimap<std::string, nullable<Base> >,
  287. ptr_multimap<std::string,Derived_class>,
  288. Derived_class>();
  289. map_container_assignment_test< ptr_multimap<std::string, nullable<Base> >,
  290. ptr_multimap<std::string, nullable<Derived_class> >,
  291. Derived_class>();
  292. test_transfer< ptr_map<int,Derived_class>, ptr_map<int,Base>, Derived_class >();
  293. test_transfer< ptr_multimap<int,Derived_class>, ptr_multimap<int,Base>, Derived_class >();
  294. string joe = "joe";
  295. string brian = "brian";
  296. string kenny = "kenny";
  297. ptr_map<string,int> m;
  298. m.insert( joe, new int( 4 ) );
  299. m.insert( brian, new int( 6 ) );
  300. BOOST_CHECK( m[ "foo" ] == 0 );
  301. m[ "bar" ] += 5;
  302. BOOST_CHECK( m[ "bar" ] == 5 );
  303. m[ joe ] += 56;
  304. m[ brian ] += 10;
  305. BOOST_CHECK_THROW( (m.insert(kenny, 0 )), bad_ptr_container_operation );
  306. BOOST_CHECK_THROW( (m.replace(m.begin(), 0 )), bad_ptr_container_operation );
  307. BOOST_CHECK_THROW( (m.at("not there")), bad_ptr_container_operation );
  308. for( ptr_map<string,int>::iterator i = m.begin();
  309. i != m.end(); ++i )
  310. {
  311. if( is_null(i) )
  312. BOOST_CHECK( false );
  313. const string& ref = i->first;
  314. hide_warning(ref);
  315. int& ref2 = *(*i).second;
  316. ref2++;
  317. }
  318. typedef ptr_map<string,Derived_class> map_type;
  319. map_type m2;
  320. m2.insert( joe, new Derived_class );
  321. //
  322. // This works fine since 'm2' is not const
  323. //
  324. m2.begin()->second->foo();
  325. //
  326. // These all return an implementation-defined proxy
  327. // with two public members: 'first' and 'second'
  328. //
  329. map_type::value_type a_value = *m2.begin();
  330. a_value.second->foo();
  331. map_type::reference a_reference = *m2.begin();
  332. a_reference.second->foo();
  333. map_type::const_reference a_creference = *const_begin(m2);
  334. hide_warning(a_creference);
  335. //
  336. //
  337. // These will fail as iterators propagate constness
  338. //
  339. //a_creference.second->foo();
  340. //a_cpointer->second->foo();
  341. //const_begin(m2)->second->foo();
  342. }
  343. #include <boost/tuple/tuple.hpp>
  344. #include <boost/iterator/zip_iterator.hpp>
  345. #include <map>
  346. #include <boost/ptr_container/ptr_map.hpp>
  347. void test_map_iterators()
  348. {
  349. using boost::zip_iterator;
  350. using boost::tuple;
  351. using boost::make_tuple;
  352. using boost::ptr_map;
  353. using std::map;
  354. //typedef map<int, int> theMapType;
  355. /*
  356. @remark: the following will not compile
  357. because of the proxy (non-reference) returned by operator*()
  358. of the ptr_map's iterator type.
  359. typedef boost::ptr_map<int, int> theMapType;
  360. typedef zip_iterator
  361. <tuple<theMapType::iterator, theMapType::iterator> > zipIter;
  362. theMapType map1;
  363. theMapType map2;
  364. zipIter zip(make_tuple(map1.begin(), map2.begin()));
  365. */
  366. }
  367. using boost::unit_test::test_suite;
  368. test_suite* init_unit_test_suite( int argc, char* argv[] )
  369. {
  370. test_suite* test = BOOST_TEST_SUITE( "Pointer Container Test Suite" );
  371. test->add( BOOST_TEST_CASE( &test_map ) );
  372. test->add( BOOST_TEST_CASE( &test_map_iterators ) );
  373. return test;
  374. }