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

source code of boost/libs/ptr_container/test/ptr_map.cpp