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 <boost/static_assert.hpp> |
13 | #include <boost/type_traits.hpp> |
14 | #include <boost/config.hpp> |
15 | #include <boost/test/unit_test.hpp> |
16 | #include <boost/lexical_cast.hpp> |
17 | #include <boost/functional/hash.hpp> |
18 | #include <algorithm> |
19 | #include <iostream> |
20 | #include <string> |
21 | #include <utility> |
22 | #include <cstdlib> |
23 | |
24 | using namespace std; |
25 | using namespace boost; |
26 | |
27 | ////////////////////////////////////////////////////////////////////////////// |
28 | // Test class 1: a class hierarchy |
29 | ////////////////////////////////////////////////////////////////////////////// |
30 | |
31 | namespace test |
32 | { |
33 | class Base |
34 | { |
35 | protected: |
36 | Base( const Base& r ) : data1(r.data1), data2(r.data2), |
37 | data3(r.data3), data(r.data) |
38 | { |
39 | #ifdef PTR_CONTAINER_DEBUG |
40 | objects++; |
41 | std::cout <<"+ " << objects << "\n" ; |
42 | #endif |
43 | } |
44 | |
45 | Base& operator=( const Base& ); |
46 | |
47 | public: // for test reasons only |
48 | int data1, data2, data3; |
49 | string data; |
50 | |
51 | public: |
52 | |
53 | Base() : data1(1), data2(2), data3(rand()%256), |
54 | data(lexical_cast<string>(arg: rand())) |
55 | { |
56 | #ifdef PTR_CONTAINER_DEBUG |
57 | objects++; |
58 | std::cout <<"+ " << objects << "\n" ; |
59 | #endif |
60 | } |
61 | |
62 | virtual ~Base() |
63 | { |
64 | #ifdef PTR_CONTAINER_DEBUG |
65 | objects--; |
66 | std::cout <<"- " << objects << "\n" ; |
67 | if( objects < 0 ) |
68 | terminate(); |
69 | #endif |
70 | } |
71 | |
72 | void print( ostream& out ) const { do_print( out); } |
73 | Base* clone() const { return do_clone(); } |
74 | void foo() { do_foo(); } |
75 | |
76 | virtual bool less_than( const Base& b ) const |
77 | { |
78 | return data3 < b.data3; |
79 | } |
80 | |
81 | virtual bool equal( const Base& b ) const |
82 | { |
83 | return data1 == b.data1 && |
84 | data2 == b.data2 && |
85 | data3 == b.data3 && |
86 | data == b.data; |
87 | } |
88 | |
89 | #ifdef PTR_CONTAINER_DEBUG |
90 | static int objects; |
91 | #endif |
92 | |
93 | private: |
94 | virtual void do_print( ostream& /*out*/ ) const { }; |
95 | virtual Base* do_clone() const { return new Base( *this ); }; |
96 | virtual void do_foo() { }; |
97 | }; |
98 | |
99 | #ifdef PTR_CONTAINER_DEBUG |
100 | int Base::objects = 0; |
101 | #endif |
102 | |
103 | |
104 | |
105 | ostream& operator<<( ostream& out, const Base& b ) |
106 | { |
107 | b.print( out ); |
108 | return out; |
109 | } |
110 | |
111 | |
112 | // |
113 | // We rely on argument dependent lookup |
114 | // for this to be found |
115 | // |
116 | inline Base* new_clone( const Base& b ) |
117 | { |
118 | return b.clone(); |
119 | } |
120 | |
121 | |
122 | |
123 | inline bool operator<( const Base& l, const Base& r ) |
124 | { |
125 | return l.less_than( b: r ); |
126 | } |
127 | |
128 | |
129 | |
130 | inline bool operator>( const Base& l, const Base& r ) |
131 | { |
132 | return r < l; |
133 | } |
134 | |
135 | |
136 | |
137 | inline bool operator==( const Base& l, const Base& r ) |
138 | { |
139 | return l.equal( b: r ); |
140 | } |
141 | |
142 | |
143 | |
144 | inline bool operator!=( const Base& l, const Base& r ) |
145 | { |
146 | return !l.equal( b: r ); |
147 | } |
148 | |
149 | |
150 | |
151 | inline std::size_t hash_value( const Base& b ) |
152 | { |
153 | std::size_t seed = 0; |
154 | boost::hash_combine( seed, v: b.data ); |
155 | boost::hash_combine( seed, v: b.data1 ); |
156 | boost::hash_combine( seed, v: b.data2 ); |
157 | boost::hash_combine( seed, v: b.data3 ); |
158 | return seed; |
159 | } |
160 | |
161 | |
162 | class Derived_class : public Base |
163 | { |
164 | protected: |
165 | Derived_class( const Derived_class& r ) : Base( r ), i_(r.i_) |
166 | { } |
167 | |
168 | public: // for test reasons only |
169 | int i_; |
170 | |
171 | private: |
172 | |
173 | virtual void do_print( ostream& out ) const |
174 | { |
175 | out << i_; |
176 | } |
177 | |
178 | |
179 | virtual Base* do_clone() const |
180 | { |
181 | return new Derived_class( *this ); |
182 | } |
183 | |
184 | virtual void do_foo() |
185 | { |
186 | ++i_; |
187 | } |
188 | |
189 | public: |
190 | Derived_class() : i_( rand() ) |
191 | { } |
192 | |
193 | virtual bool less_than( const Base& b ) const |
194 | { |
195 | const Derived_class& d = dynamic_cast<const Derived_class&>( b ); |
196 | return i_ < d.i_; |
197 | } |
198 | }; |
199 | |
200 | |
201 | |
202 | inline std::size_t hash_value( const Derived_class& b ) |
203 | { |
204 | std::size_t seed = hash_value( b: static_cast<const Base&>( b ) ); |
205 | boost::hash_combine( seed, v: b.i_ ); |
206 | return seed; |
207 | } |
208 | } |
209 | |
210 | using test::Base; |
211 | using test::Derived_class; |
212 | |
213 | ////////////////////////////////////////////////////////////////////////////// |
214 | // Test class 2: a value class |
215 | ////////////////////////////////////////////////////////////////////////////// |
216 | |
217 | class Value |
218 | { |
219 | public: // for test reasons only |
220 | string s_; |
221 | |
222 | public: |
223 | |
224 | Value() : s_( boost::lexical_cast<string>( arg: rand() ) ) |
225 | {} |
226 | |
227 | ~Value() { /** debug code here */ } |
228 | |
229 | string name() const |
230 | { |
231 | return s_; |
232 | } |
233 | }; |
234 | |
235 | |
236 | |
237 | inline bool operator<( const Value& l, const Value& r ) |
238 | { |
239 | return l.name() < r.name(); |
240 | } |
241 | |
242 | |
243 | |
244 | inline bool operator>( const Value& l, const Value& r ) |
245 | { |
246 | return l.name() > r.name(); |
247 | } |
248 | |
249 | |
250 | |
251 | inline bool operator==( const Value& l, const Value& r ) |
252 | { |
253 | return l.name() == r.name(); |
254 | } |
255 | |
256 | |
257 | |
258 | inline bool operator!=( const Value& l, const Value& r ) |
259 | { |
260 | return l.name() != r.name(); |
261 | } |
262 | |
263 | |
264 | |
265 | inline ostream& operator<<( ostream& out, const Value& v ) |
266 | { |
267 | return out << v.name() << " " ; |
268 | } |
269 | |
270 | |
271 | |
272 | inline std::size_t hash_value( const Value& v ) |
273 | { |
274 | return boost::hash_value( v: v.s_ ); |
275 | } |
276 | |
277 | // |
278 | // used to hide "unused variable" warnings |
279 | // |
280 | template< class T > |
281 | inline void hide_warning( T& /*r*/ ) |
282 | { } |
283 | |
284 | // |
285 | // used to customize tests for circular_buffer |
286 | // |
287 | template< class Cont > |
288 | struct set_capacity |
289 | { |
290 | void operator()( Cont& ) const |
291 | { } |
292 | }; |
293 | |
294 | // |
295 | // transfer() test |
296 | // |
297 | |
298 | template< class Cont1, class Cont2 > |
299 | void transfer_test( Cont1& from, Cont2& to ) |
300 | { |
301 | BOOST_TEST_MESSAGE( "starting container transfer test" ); |
302 | BOOST_CHECK( !from.empty() ); |
303 | to. BOOST_NESTED_TEMPLATE transfer<Cont1>( from ); |
304 | BOOST_CHECK( !to.empty() ); |
305 | BOOST_TEST_MESSAGE( "finishing container transfer test" ); |
306 | } |
307 | |
308 | |
309 | // |
310 | // test of copy operations |
311 | // |
312 | |
313 | template< class BaseContainer, class DerivedContainer, class Derived > |
314 | void container_assignment_test() |
315 | { |
316 | BOOST_TEST_MESSAGE( "starting container assignment test" ); |
317 | |
318 | DerivedContainer derived; |
319 | set_capacity<DerivedContainer>()( derived ); |
320 | derived.insert( derived.begin(), new Derived ); |
321 | derived.insert( derived.begin(), new Derived ); |
322 | |
323 | BaseContainer base( derived ); |
324 | BOOST_CHECK_EQUAL( derived.size(), base.size() ); |
325 | base.clear(); |
326 | base = derived; |
327 | BOOST_CHECK_EQUAL( derived.size(), base.size() ); |
328 | BaseContainer base2( base ); |
329 | BOOST_CHECK_EQUAL( base2.size(), base.size() ); |
330 | base2 = base; |
331 | BOOST_CHECK_EQUAL( base2.size(), base.size() ); |
332 | base = base; |
333 | |
334 | BOOST_TEST_MESSAGE( "finished container assignment test" ); |
335 | } |
336 | |
337 | |
338 | |