2 // Boost.Pointer Container
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)
9 // For more information, see http://www.boost.org/libs/ptr_container/
12 #include "test_data.hpp"
13 #include <boost/test/unit_test.hpp>
14 #include <boost/ptr_container/exception.hpp>
15 #include <boost/range/sub_range.hpp>
16 #include <boost/cast.hpp>
23 // abstract base class definition
27 virtual ~abstract_base() {}
28 virtual void foo() = 0;
29 virtual abstract_base
* clone() const = 0;
32 struct implementation
: abstract_base
37 implementation( const implementation
& )
40 implementation( int, std::string
, int, std::string
)
44 virtual abstract_base
* clone() const
46 return new implementation( *this );
50 inline std::ostream
& operator<<( std::ostream
& out
, const abstract_base
& r
)
55 inline abstract_base
* new_clone( const abstract_base
& r
)
64 template< typename C
, typename B
, typename T
>
68 Key
get_next_key( const Key
& k
);
71 int get_next_key
<int>( const int& )
77 std::string get_next_key
<std::string
>( const std::string
& )
79 return boost::lexical_cast
<std::string
>( rand() );
83 template< typename C
, typename B
, typename T
>
86 using namespace boost
;
88 BOOST_TEST_MESSAGE( "starting associative container test" );
89 enum { max_cnt
= 10, size
= 100 };
91 BOOST_CHECK( c
.size() == 0 );
93 const C
c2( c
.begin(), c
.end() );
94 BOOST_CHECK( c
.size() == c2
.size() );
98 BOOST_TEST_MESSAGE( "finished construction test" );
100 BOOST_DEDUCED_TYPENAME
C::allocator_type alloc
= c
.get_allocator();
101 BOOST_DEDUCED_TYPENAME
C::iterator i
= c
.begin();
102 BOOST_DEDUCED_TYPENAME
C::const_iterator ci
= c2
.begin();
103 BOOST_DEDUCED_TYPENAME
C::iterator i2
= c
.end();
104 BOOST_DEDUCED_TYPENAME
C::const_iterator ci2
= c2
.begin();
105 BOOST_DEDUCED_TYPENAME
C::reverse_iterator ri
= c
.rbegin();
106 BOOST_DEDUCED_TYPENAME
C::const_reverse_iterator cri
= c2
.rbegin();
107 BOOST_DEDUCED_TYPENAME
C::reverse_iterator rv2
= c
.rend();
108 BOOST_DEDUCED_TYPENAME
C::const_reverse_iterator cvr2
= c2
.rend();
110 BOOST_DEDUCED_TYPENAME
C::key_type a_key
;
112 BOOST_TEST_MESSAGE( "finished iterator test" );
114 BOOST_DEDUCED_TYPENAME
C::size_type s
= c
.size();
115 BOOST_DEDUCED_TYPENAME
C::size_type s2
= c
.max_size();
117 BOOST_CHECK_EQUAL( c
.size(), s
);
120 BOOST_TEST_MESSAGE( "finished accessors test" );
122 a_key
= get_next_key( a_key
);
123 c
.insert( a_key
, new T
);
124 a_key
= get_next_key( a_key
);
125 c
.insert( a_key
, new T
);
126 c3
.insert( c
.begin(), c
.end() );
128 c
.erase( c
.begin() );
129 BOOST_CHECK( c3
.end() == c3
.erase( boost::make_iterator_range(c3
) ) );
132 BOOST_CHECK( c3
.empty() );
136 BOOST_CHECK( !c3
.empty() );
138 BOOST_CHECK( c3
.empty() );
139 BOOST_TEST_MESSAGE( "finished modifiers test" );
142 a_key
= get_next_key( a_key
);
143 c
.insert( a_key
, new T
);
144 a_key
= get_next_key( a_key
);
145 c
.insert( a_key
, std::auto_ptr
<T
>( new T
) );
146 typename
C::auto_type ptr2
= c
.release( c
.begin() );
147 std::auto_ptr
<C
> ap
= c
.release();
149 BOOST_TEST_MESSAGE( "finished release/clone test" );
152 a_key
= get_next_key( a_key
);
153 c3
.insert( a_key
, new T
);
154 a_key
= get_next_key( a_key
);
155 c3
.insert( a_key
, new T
);
157 c
. BOOST_NESTED_TEMPLATE transfer
<C
>( c3
.begin(), c3
);
158 c
. BOOST_NESTED_TEMPLATE transfer
<C
>( c3
.begin(), c3
.end(), c3
);
159 BOOST_CHECK( c3
.empty() );
160 BOOST_CHECK( !c
.empty() );
161 c3
. BOOST_NESTED_TEMPLATE transfer
<C
>( c
);
162 BOOST_CHECK( !c3
.empty() );
163 BOOST_CHECK( c
.empty() );
164 #ifdef BOOST_NO_SFINAE
166 c
. BOOST_NESTED_TEMPLATE transfer
<C
>( make_iterator_range(c3
), c3
);
167 BOOST_CHECK( !c
.empty() );
168 BOOST_CHECK( c3
.empty() );
169 c3
. BOOST_NESTED_TEMPLATE transfer
<C
>(c
);
171 BOOST_TEST_MESSAGE( "finished transfer test" );
173 BOOST_CHECK( !c3
.empty() );
174 c3
.replace( c3
.begin(), new T
);
175 c3
.replace( c3
.begin(), std::auto_ptr
<T
>( new T
) );
176 BOOST_TEST_MESSAGE( "finished set/map interface test" );
178 // @todo: make macro with algorithms so that the right erase() is called.
180 // c.unique( std::not_equal_to<T>() );
182 // c.remove_if( std::binder1st< std::equal_to<T> >( T() ) );
185 sub_range
<const C
> csub
;
187 i
= c
.find( get_next_key( a_key
) );
188 ci
= c2
.find( get_next_key( a_key
) );
189 c2
.count( get_next_key( a_key
) );
190 i
= c
.lower_bound( get_next_key( a_key
) );
191 ci
= c2
.lower_bound( get_next_key( a_key
) );
192 i
= c
.upper_bound( get_next_key( a_key
) );
193 ci
= c2
.upper_bound( get_next_key( a_key
) );
194 sub
= c
.equal_range( get_next_key( a_key
) );
195 csub
= c2
.equal_range( get_next_key( a_key
) );
199 c
.at( get_next_key( a_key
) );
201 catch( const bad_ptr_container_operation
& )
206 c2
.at( get_next_key( a_key
) );
208 catch( const bad_ptr_container_operation
& )
211 BOOST_TEST_MESSAGE( "finished algorithms interface test" );
213 typename
C::iterator it
= c
.begin(), e
= c
.end();
214 for( ; it
!= e
; ++it
)
216 std::cout
<< "\n mapped value = " << *it
->second
<< " key = " << it
->first
;
217 //std::cout << "\n mapped value = " << it.value() << " key = " << it.key();
220 typename
C::reverse_iterator rit
= c
.rbegin(), re
= c
.rend();
221 for( ; rit
!= re
; ++rit
)
223 std::cout
<< "\n mapped value = " << *rit
->second
<< " key = " << rit
->first
;
224 //std::cout << "\n mapped value = " << rit.value() << " key = " << rit.key();
225 //std::cout << "\n mapped value (base) = "
226 // << rit.base().value() << " key = " << rit.base().key();
229 typename
C::const_reverse_iterator crit
= c2
.rbegin(), cre
= c2
.rend();
230 for( ; crit
!= cre
; ++crit
)
232 std::cout
<< "\n mapped value = " << *(*crit
).second
<< " key = " << (*crit
).first
;
233 //std::cout << "\n mapped value = " << crit.value() << " key = " << crit.key();
234 //std::cout << "\n mapped value (base) = "
235 // << crit.base().value() << " key = " << crit.base().key();
238 BOOST_TEST_MESSAGE( "finished iterator test" );
240 a_key
= get_next_key( a_key
);
241 c
.insert( a_key
, new T
);
249 template< class CDerived
, class CBase
, class T
>
255 int key
= get_next_key( key
);
256 from
.insert( key
, new T
);
257 key
= get_next_key( key
);
258 from
.insert( key
, new T
);
259 transfer_test( from
, to
);
264 template< class BaseContainer
, class DerivedContainer
, class Derived
>
265 void map_container_assignment_test()
267 DerivedContainer derived
;
268 std::string
foo( "foo" );
269 std::string
bar( "foo" );
270 derived
.insert( foo
, new Derived
);
271 derived
.insert( bar
, new Derived
);
273 BaseContainer
base_container( derived
);
274 BOOST_CHECK_EQUAL( derived
.size(), base_container
.size() );
275 base_container
.clear();
276 base_container
= derived
;
277 BOOST_CHECK_EQUAL( derived
.size(), base_container
.size() );
279 BaseContainer
base2( base_container
);
280 BOOST_CHECK_EQUAL( base2
.size(), base_container
.size() );
281 base2
= base_container
;
282 BOOST_CHECK_EQUAL( base2
.size(), base_container
.size() );
283 base_container
= base_container
;
288 #include <boost/ptr_container/ptr_map.hpp>
294 ptr_map_test
< ptr_map
<int, Base
>, Base
, Derived_class
>();
295 ptr_map_test
< ptr_map
<int, Value
>, Value
, Value
>();
296 ptr_map_test
< ptr_map
<int, nullable
<Base
> >, Base
, Derived_class
>();
297 ptr_map_test
< ptr_map
<int, nullable
<Value
> >, Value
, Value
>();
298 ptr_map_test
< ptr_map
<int, abstract_base
>, abstract_base
, implementation
>();
300 ptr_map_test
< ptr_multimap
<int,Base
>, Base
, Derived_class
>();
301 ptr_map_test
< ptr_multimap
<int,Value
>, Value
, Value
>();
302 ptr_map_test
< ptr_multimap
<int, nullable
<Base
> >, Base
, Derived_class
>();
303 ptr_map_test
< ptr_multimap
<int, nullable
<Value
> >, Value
, Value
>();
305 map_container_assignment_test
< ptr_map
<std::string
,Base
>,
306 ptr_map
<std::string
,Derived_class
>,
308 map_container_assignment_test
< ptr_map
<std::string
, nullable
<Base
> >,
309 ptr_map
<std::string
,Derived_class
>,
311 map_container_assignment_test
< ptr_map
<std::string
, nullable
<Base
> >,
312 ptr_map
<std::string
, nullable
<Derived_class
> >,
314 map_container_assignment_test
< ptr_multimap
<std::string
,Base
>,
315 ptr_multimap
<std::string
,Derived_class
>,
317 map_container_assignment_test
< ptr_multimap
<std::string
, nullable
<Base
> >,
318 ptr_multimap
<std::string
,Derived_class
>,
320 map_container_assignment_test
< ptr_multimap
<std::string
, nullable
<Base
> >,
321 ptr_multimap
<std::string
, nullable
<Derived_class
> >,
325 test_transfer
< ptr_map
<int,Derived_class
>, ptr_map
<int,Base
>, Derived_class
>();
326 test_transfer
< ptr_multimap
<int,Derived_class
>, ptr_multimap
<int,Base
>, Derived_class
>();
329 string brian
= "brian";
330 string kenny
= "kenny";
332 ptr_map
<string
,int> m
;
333 m
.insert( joe
, new int( 4 ) );
334 m
.insert( brian
, new int( 6 ) );
335 BOOST_CHECK( m
[ "foo" ] == 0 );
337 BOOST_CHECK( m
[ "bar" ] == 5 );
341 BOOST_CHECK_THROW( (m
.insert(kenny
, 0 )), bad_ptr_container_operation
);
342 BOOST_CHECK_THROW( (m
.replace(m
.begin(), 0 )), bad_ptr_container_operation
);
343 BOOST_CHECK_THROW( (m
.at("not there")), bad_ptr_container_operation
);
345 for( ptr_map
<string
,int>::iterator i
= m
.begin();
349 BOOST_CHECK( false );
350 const string
& ref
= i
->first
;
352 int& ref2
= *(*i
).second
;
356 typedef ptr_map
<string
,Derived_class
> map_type
;
358 m2
.insert( joe
, new Derived_class
);
360 // This works fine since 'm2' is not const
362 m2
.begin()->second
->foo();
365 // These all return an implementation-defined proxy
366 // with two public members: 'first' and 'second'
368 map_type::value_type a_value
= *m2
.begin();
369 a_value
.second
->foo();
370 map_type::reference a_reference
= *m2
.begin();
371 a_reference
.second
->foo();
372 map_type::const_reference a_creference
= *const_begin(m2
);
376 // These will fail as iterators propagate constness
378 //a_creference.second->foo();
379 //a_cpointer->second->foo();
380 //const_begin(m2)->second->foo();
384 #include <boost/tuple/tuple.hpp>
385 #include <boost/iterator/zip_iterator.hpp>
387 #include <boost/ptr_container/ptr_map.hpp>
389 void test_map_iterators()
391 using boost::zip_iterator
;
393 using boost::make_tuple
;
394 using boost::ptr_map
;
397 //typedef map<int, int> theMapType;
399 @remark: the following will not compile
400 because of the proxy (non-reference) returned by operator*()
401 of the ptr_map's iterator type.
403 typedef boost::ptr_map<int, int> theMapType;
405 <tuple<theMapType::iterator, theMapType::iterator> > zipIter;
408 zipIter zip(make_tuple(map1.begin(), map2.begin()));
414 using boost::unit_test::test_suite
;
416 test_suite
* init_unit_test_suite( int argc
, char* argv
[] )
418 test_suite
* test
= BOOST_TEST_SUITE( "Pointer Container Test Suite" );
420 test
->add( BOOST_TEST_CASE( &test_map
) );
421 test
->add( BOOST_TEST_CASE( &test_map_iterators
) );