1 | // Copyright (C) 2003, Fernando Luis Cacciola Carballal. |
---|
2 | // |
---|
3 | // Use, modification, and distribution is subject to the Boost Software |
---|
4 | // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
---|
5 | // http://www.boost.org/LICENSE_1_0.txt) |
---|
6 | // |
---|
7 | // See http://www.boost.org/lib/optional for documentation. |
---|
8 | // |
---|
9 | // You are welcome to contact the author at: |
---|
10 | // fernando_cacciola@hotmail.com |
---|
11 | // |
---|
12 | #include<iostream> |
---|
13 | #include<stdexcept> |
---|
14 | #include<string> |
---|
15 | |
---|
16 | #define BOOST_ENABLE_ASSERT_HANDLER |
---|
17 | |
---|
18 | #include "boost/optional.hpp" |
---|
19 | |
---|
20 | #ifdef __BORLANDC__ |
---|
21 | #pragma hdrstop |
---|
22 | #endif |
---|
23 | |
---|
24 | #include "boost/none.hpp" |
---|
25 | |
---|
26 | #include "boost/test/minimal.hpp" |
---|
27 | |
---|
28 | #include "optional_test_common.cpp" |
---|
29 | |
---|
30 | template<class T> |
---|
31 | inline void check_ref_uninitialized_const ( optional<T&> const& opt ) |
---|
32 | { |
---|
33 | #ifndef BOOST_OPTIONAL_NO_NULL_COMPARE |
---|
34 | BOOST_CHECK( opt == 0 ) ; |
---|
35 | #endif |
---|
36 | BOOST_CHECK( !opt ) ; |
---|
37 | } |
---|
38 | template<class T> |
---|
39 | inline void check_ref_uninitialized ( optional<T&>& opt ) |
---|
40 | { |
---|
41 | #ifndef BOOST_OPTIONAL_NO_NULL_COMPARE |
---|
42 | BOOST_CHECK( opt == 0 ) ; |
---|
43 | #endif |
---|
44 | BOOST_CHECK( !opt ) ; |
---|
45 | |
---|
46 | check_ref_uninitialized_const(opt); |
---|
47 | } |
---|
48 | |
---|
49 | template<class T> |
---|
50 | inline void check_ref_initialized_const ( optional<T&> const& opt ) |
---|
51 | { |
---|
52 | BOOST_CHECK( opt ) ; |
---|
53 | |
---|
54 | #ifndef BOOST_OPTIONAL_NO_NULL_COMPARE |
---|
55 | BOOST_CHECK( opt != 0 ) ; |
---|
56 | #endif |
---|
57 | |
---|
58 | BOOST_CHECK ( !!opt ) ; |
---|
59 | } |
---|
60 | |
---|
61 | template<class T> |
---|
62 | inline void check_ref_initialized ( optional<T&>& opt ) |
---|
63 | { |
---|
64 | BOOST_CHECK( opt ) ; |
---|
65 | |
---|
66 | #ifndef BOOST_OPTIONAL_NO_NULL_COMPARE |
---|
67 | BOOST_CHECK( opt != 0 ) ; |
---|
68 | #endif |
---|
69 | |
---|
70 | BOOST_CHECK ( !!opt ) ; |
---|
71 | |
---|
72 | check_ref_initialized_const(opt); |
---|
73 | } |
---|
74 | |
---|
75 | template<class T> |
---|
76 | inline void check_ref_value_const ( optional<T&> const& opt, T const& v, T const& z ) |
---|
77 | { |
---|
78 | BOOST_CHECK( *opt == v ) ; |
---|
79 | BOOST_CHECK( *opt != z ) ; |
---|
80 | BOOST_CHECK( opt.get() == v ) ; |
---|
81 | BOOST_CHECK( opt.get() != z ) ; |
---|
82 | } |
---|
83 | |
---|
84 | template<class T> |
---|
85 | inline void check_ref_value ( optional<T&>& opt, T const& v, T const& z ) |
---|
86 | { |
---|
87 | BOOST_CHECK( *opt == v ) ; |
---|
88 | BOOST_CHECK( *opt != z ) ; |
---|
89 | BOOST_CHECK( opt.get() == v ) ; |
---|
90 | BOOST_CHECK( opt.get() != z ) ; |
---|
91 | |
---|
92 | check_ref_value_const(opt,v,z); |
---|
93 | } |
---|
94 | |
---|
95 | // |
---|
96 | // Basic test. |
---|
97 | // Check ordinary functionality: |
---|
98 | // Initialization, assignment, comparison and value-accessing. |
---|
99 | // |
---|
100 | template<class T> |
---|
101 | void test_basics( T const* ) |
---|
102 | { |
---|
103 | TRACE( std::endl << BOOST_CURRENT_FUNCTION ); |
---|
104 | |
---|
105 | T z(0); |
---|
106 | |
---|
107 | T original_a(1); |
---|
108 | |
---|
109 | T a(1); |
---|
110 | |
---|
111 | T b(2); |
---|
112 | |
---|
113 | T c(10); |
---|
114 | |
---|
115 | T& aref = a ; |
---|
116 | T& bref = b ; |
---|
117 | |
---|
118 | // Default construction. |
---|
119 | // 'def' state is Uninitialized. |
---|
120 | // T::T() is not called |
---|
121 | optional<T&> def ; |
---|
122 | check_ref_uninitialized(def); |
---|
123 | |
---|
124 | // Direct initialization. |
---|
125 | // 'oa' state is Initialized and binds to 'a' |
---|
126 | // T::T( T const& x ) is NOT used becasue the optional holds a reference. |
---|
127 | set_pending_copy( ARG(T) ) ; |
---|
128 | optional<T&> oa ( aref ) ; |
---|
129 | check_is_pending_copy( ARG(T) ); |
---|
130 | check_ref_initialized(oa); |
---|
131 | check_ref_value(oa,a,z); |
---|
132 | *oa = b ; // changes the value of 'a' through the reference |
---|
133 | BOOST_CHECK( a == b ) ; |
---|
134 | |
---|
135 | |
---|
136 | // Copy initialization. |
---|
137 | // T::T ( T const& x ) is NOT used becasue the optional holds a reference. |
---|
138 | set_pending_copy( ARG(T) ) ; |
---|
139 | optional<T&> const oa2 ( oa ) ; |
---|
140 | check_is_pending_copy( ARG(T) ) ; |
---|
141 | check_ref_initialized_const(oa2); |
---|
142 | check_ref_value_const(oa2,a,z); |
---|
143 | *oa2 = original_a ; // restores the value of 'a' through the reference |
---|
144 | BOOST_CHECK( a == original_a ) ; |
---|
145 | |
---|
146 | optional<T&> ob ; |
---|
147 | |
---|
148 | // Value-Assignment upon Uninitialized optional. |
---|
149 | // T::T ( T const& x ) is NOT used becasue the optional holds a reference. |
---|
150 | set_pending_copy( ARG(T) ) ; |
---|
151 | ob = a ; // Binds ob to a temporary non-const refererence to 'a' |
---|
152 | check_is_pending_copy( ARG(T) ) ; |
---|
153 | check_ref_initialized(ob); |
---|
154 | check_ref_value(ob,a,z); |
---|
155 | a = c; |
---|
156 | check_ref_value(ob,a,z); |
---|
157 | |
---|
158 | // Value-Assignment upon Initialized optional. |
---|
159 | // T::operator= ( T const& x ) is used. |
---|
160 | set_pending_assign( ARG(T) ) ; |
---|
161 | ob = b ; // Rebinds 'ob' to 'b' (without changing 'a') |
---|
162 | check_is_pending_assign( ARG(T) ) ; |
---|
163 | check_ref_initialized(ob); |
---|
164 | check_ref_value(ob,b,z); |
---|
165 | BOOST_CHECK(a == c); // From a=c in previous test |
---|
166 | b = c; |
---|
167 | check_ref_value(ob,b,z); |
---|
168 | |
---|
169 | |
---|
170 | // Assignment initialization. |
---|
171 | // T::T ( T const& x ) is NOT used becasue the optional holds a reference. |
---|
172 | set_pending_copy( ARG(T) ) ; |
---|
173 | optional<T&> const oa3 = b ; |
---|
174 | check_is_pending_copy( ARG(T) ) ; |
---|
175 | check_ref_initialized_const(oa3); |
---|
176 | check_ref_value_const(oa3,b,z); |
---|
177 | |
---|
178 | |
---|
179 | // Assignment |
---|
180 | // T::operator=( T const& x ) is used. |
---|
181 | set_pending_assign( ARG(T) ) ; |
---|
182 | oa = ob ; // Rebinds 'a' to 'b' |
---|
183 | check_is_pending_assign( ARG(T) ) ; |
---|
184 | check_ref_initialized(oa); |
---|
185 | a = original_a ; |
---|
186 | check_ref_value(oa,b,z); |
---|
187 | |
---|
188 | // Uninitializing Assignment upon Initialized Optional |
---|
189 | // T::~T() is NOT used becasue the optional holds a reference. |
---|
190 | set_pending_dtor( ARG(T) ) ; |
---|
191 | set_pending_copy( ARG(T) ) ; |
---|
192 | oa = def ; |
---|
193 | check_is_pending_dtor( ARG(T) ) ; |
---|
194 | check_is_pending_copy( ARG(T) ) ; |
---|
195 | check_ref_uninitialized(oa); |
---|
196 | |
---|
197 | // Uninitializing Assignment upon Uninitialized Optional |
---|
198 | // (Dtor is not called this time) |
---|
199 | set_pending_dtor( ARG(T) ) ; |
---|
200 | set_pending_copy( ARG(T) ) ; |
---|
201 | oa = def ; |
---|
202 | check_is_pending_dtor( ARG(T) ) ; |
---|
203 | check_is_pending_copy( ARG(T) ) ; |
---|
204 | check_ref_uninitialized(oa); |
---|
205 | |
---|
206 | |
---|
207 | // Deinitialization of Initialized Optional |
---|
208 | // T::~T() is NOT used becasue the optional holds a reference. |
---|
209 | set_pending_dtor( ARG(T) ) ; |
---|
210 | ob.reset(); |
---|
211 | check_is_pending_dtor( ARG(T) ) ; |
---|
212 | check_ref_uninitialized(ob); |
---|
213 | |
---|
214 | // Deinitialization of Uninitialized Optional |
---|
215 | // T::~T() is not called this time |
---|
216 | set_pending_dtor( ARG(T) ) ; |
---|
217 | ob.reset(); |
---|
218 | check_is_pending_dtor( ARG(T) ) ; |
---|
219 | check_ref_uninitialized(ob); |
---|
220 | } |
---|
221 | |
---|
222 | // |
---|
223 | // This verifies relational operators. |
---|
224 | // |
---|
225 | template<class T> |
---|
226 | void test_relops( T const* ) |
---|
227 | { |
---|
228 | TRACE( std::endl << BOOST_CURRENT_FUNCTION ); |
---|
229 | |
---|
230 | reset_throw_on_copy( ARG(T) ) ; |
---|
231 | |
---|
232 | T v0(18); |
---|
233 | T v1(19); |
---|
234 | T v2(19); |
---|
235 | |
---|
236 | optional<T&> def0 ; |
---|
237 | optional<T&> def1 ; |
---|
238 | optional<T&> opt0(v0); |
---|
239 | optional<T&> opt1(v1); |
---|
240 | optional<T&> opt2(v2); |
---|
241 | |
---|
242 | // Check identity |
---|
243 | BOOST_CHECK ( def0 == def0 ) ; |
---|
244 | BOOST_CHECK ( opt0 == opt0 ) ; |
---|
245 | BOOST_CHECK ( !(def0 != def0) ) ; |
---|
246 | BOOST_CHECK ( !(opt0 != opt0) ) ; |
---|
247 | |
---|
248 | // Check when both are uininitalized. |
---|
249 | BOOST_CHECK ( def0 == def1 ) ; // both uninitialized compare equal |
---|
250 | BOOST_CHECK ( !(def0 < def1) ) ; // uninitialized is never less than uninitialized |
---|
251 | BOOST_CHECK ( !(def0 > def1) ) ; // uninitialized is never greater than uninitialized |
---|
252 | BOOST_CHECK ( !(def0 != def1) ) ; |
---|
253 | BOOST_CHECK ( def0 <= def1 ) ; |
---|
254 | BOOST_CHECK ( def0 >= def1 ) ; |
---|
255 | |
---|
256 | // Check when only lhs is uninitialized. |
---|
257 | BOOST_CHECK ( def0 != opt0 ) ; // uninitialized is never equal to initialized |
---|
258 | BOOST_CHECK ( !(def0 == opt0) ) ; |
---|
259 | BOOST_CHECK ( def0 < opt0 ) ; // uninitialized is always less than initialized |
---|
260 | BOOST_CHECK ( !(def0 > opt0) ) ; |
---|
261 | BOOST_CHECK ( def0 <= opt0 ) ; |
---|
262 | BOOST_CHECK ( !(def0 >= opt0) ) ; |
---|
263 | |
---|
264 | // Check when only rhs is uninitialized. |
---|
265 | BOOST_CHECK ( opt0 != def0 ) ; // initialized is never equal to uninitialized |
---|
266 | BOOST_CHECK ( !(opt0 == def0) ) ; |
---|
267 | BOOST_CHECK ( !(opt0 < def0) ) ; // initialized is never less than uninitialized |
---|
268 | BOOST_CHECK ( opt0 > def0 ) ; |
---|
269 | BOOST_CHECK ( !(opt0 <= def0) ) ; |
---|
270 | BOOST_CHECK ( opt0 >= opt0 ) ; |
---|
271 | |
---|
272 | // If both are initialized, values are compared |
---|
273 | BOOST_CHECK ( opt0 != opt1 ) ; |
---|
274 | BOOST_CHECK ( opt1 == opt2 ) ; |
---|
275 | BOOST_CHECK ( opt0 < opt1 ) ; |
---|
276 | BOOST_CHECK ( opt1 > opt0 ) ; |
---|
277 | BOOST_CHECK ( opt1 <= opt2 ) ; |
---|
278 | BOOST_CHECK ( opt1 >= opt0 ) ; |
---|
279 | } |
---|
280 | |
---|
281 | template<class T> |
---|
282 | void test_none( T const* ) |
---|
283 | { |
---|
284 | TRACE( std::endl << BOOST_CURRENT_FUNCTION ); |
---|
285 | |
---|
286 | using boost::none ; |
---|
287 | |
---|
288 | T a(1234); |
---|
289 | |
---|
290 | optional<T&> def0 ; |
---|
291 | optional<T&> def1(none) ; |
---|
292 | optional<T&> non_def(a) ; |
---|
293 | |
---|
294 | BOOST_CHECK ( def0 == none ) ; |
---|
295 | BOOST_CHECK ( non_def != none ) ; |
---|
296 | BOOST_CHECK ( !def1 ) ; |
---|
297 | |
---|
298 | non_def = none ; |
---|
299 | BOOST_CHECK ( !non_def ) ; |
---|
300 | } |
---|
301 | |
---|
302 | template<class T> |
---|
303 | void test_arrow( T const* ) |
---|
304 | { |
---|
305 | TRACE( std::endl << BOOST_CURRENT_FUNCTION ); |
---|
306 | |
---|
307 | T a(1234); |
---|
308 | |
---|
309 | optional<T&> oa(a) ; |
---|
310 | optional<T&> const coa(a) ; |
---|
311 | |
---|
312 | BOOST_CHECK ( coa->V() == 1234 ) ; |
---|
313 | |
---|
314 | oa->V() = 4321 ; |
---|
315 | |
---|
316 | BOOST_CHECK ( a.V() = 4321 ) ; |
---|
317 | } |
---|
318 | |
---|
319 | void test_with_builtin_types() |
---|
320 | { |
---|
321 | TRACE( std::endl << BOOST_CURRENT_FUNCTION ); |
---|
322 | |
---|
323 | test_basics( ARG(double) ); |
---|
324 | test_relops( ARG(double) ) ; |
---|
325 | test_none ( ARG(double) ) ; |
---|
326 | } |
---|
327 | |
---|
328 | void test_with_class_type() |
---|
329 | { |
---|
330 | TRACE( std::endl << BOOST_CURRENT_FUNCTION ); |
---|
331 | |
---|
332 | test_basics( ARG(X) ); |
---|
333 | test_relops( ARG(X) ) ; |
---|
334 | test_none ( ARG(X) ) ; |
---|
335 | test_arrow ( ARG(X) ) ; |
---|
336 | |
---|
337 | BOOST_CHECK ( X::count == 0 ) ; |
---|
338 | } |
---|
339 | |
---|
340 | int test_main( int, char* [] ) |
---|
341 | { |
---|
342 | try |
---|
343 | { |
---|
344 | test_with_class_type(); |
---|
345 | test_with_builtin_types(); |
---|
346 | } |
---|
347 | catch ( ... ) |
---|
348 | { |
---|
349 | BOOST_ERROR("Unexpected Exception caught!"); |
---|
350 | } |
---|
351 | |
---|
352 | return 0; |
---|
353 | } |
---|
354 | |
---|
355 | |
---|