]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
b32b8144 | 31 | namespace test |
7c673cae | 32 | { |
b32b8144 FG |
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>(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 | |
7c673cae | 102 | |
7c673cae | 103 | |
7c673cae | 104 | |
b32b8144 | 105 | ostream& operator<<( ostream& out, const Base& b ) |
7c673cae | 106 | { |
b32b8144 FG |
107 | b.print( out ); |
108 | return out; | |
7c673cae FG |
109 | } |
110 | ||
b32b8144 FG |
111 | |
112 | // | |
113 | // We rely on argument dependent lookup | |
114 | // for this to be found | |
115 | // | |
116 | inline Base* new_clone( const Base& b ) | |
7c673cae | 117 | { |
b32b8144 | 118 | return b.clone(); |
7c673cae FG |
119 | } |
120 | ||
7c673cae | 121 | |
b32b8144 FG |
122 | |
123 | inline bool operator<( const Base& l, const Base& r ) | |
7c673cae | 124 | { |
b32b8144 | 125 | return l.less_than( r ); |
7c673cae FG |
126 | } |
127 | ||
b32b8144 FG |
128 | |
129 | ||
130 | inline bool operator>( const Base& l, const Base& r ) | |
7c673cae | 131 | { |
b32b8144 | 132 | return r < l; |
7c673cae | 133 | } |
b32b8144 FG |
134 | |
135 | ||
136 | ||
137 | inline bool operator==( const Base& l, const Base& r ) | |
7c673cae | 138 | { |
b32b8144 | 139 | return l.equal( r ); |
7c673cae FG |
140 | } |
141 | ||
142 | ||
b32b8144 FG |
143 | |
144 | inline bool operator!=( const Base& l, const Base& r ) | |
7c673cae | 145 | { |
b32b8144 | 146 | return !l.equal( r ); |
7c673cae FG |
147 | } |
148 | ||
b32b8144 FG |
149 | |
150 | ||
151 | inline std::size_t hash_value( const Base& b ) | |
7c673cae | 152 | { |
b32b8144 FG |
153 | std::size_t seed = 0; |
154 | boost::hash_combine( seed, b.data ); | |
155 | boost::hash_combine( seed, b.data1 ); | |
156 | boost::hash_combine( seed, b.data2 ); | |
157 | boost::hash_combine( seed, b.data3 ); | |
158 | return seed; | |
7c673cae FG |
159 | } |
160 | ||
b32b8144 FG |
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 ) | |
7c673cae | 203 | { |
b32b8144 FG |
204 | std::size_t seed = hash_value( static_cast<const Base&>( b ) ); |
205 | boost::hash_combine( seed, b.i_ ); | |
206 | return seed; | |
7c673cae | 207 | } |
7c673cae FG |
208 | } |
209 | ||
b32b8144 FG |
210 | using test::Base; |
211 | using test::Derived_class; | |
212 | ||
7c673cae FG |
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>( 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.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 |