• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2014 Andrzej Krzemienski.
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: akrzemi1@gmail.com
10 
11 
12 #include "boost/optional/optional.hpp"
13 
14 #ifdef __BORLANDC__
15 #pragma hdrstop
16 #endif
17 
18 #include "boost/core/addressof.hpp"
19 #include "boost/core/enable_if.hpp"
20 #include "boost/core/lightweight_test.hpp"
21 #include "testable_classes.hpp"
22 
23 using boost::optional;
24 using boost::none;
25 
26 struct CountingClass
27 {
28   static int count;
29   static int assign_count;
CountingClassCountingClass30   CountingClass() { ++count; }
CountingClassCountingClass31   CountingClass(const CountingClass&) { ++count; }
operator =CountingClass32   CountingClass& operator=(const CountingClass&) { ++assign_count; return *this; }
~CountingClassCountingClass33   ~CountingClass() { ++count; }
34 };
35 
36 int CountingClass::count = 0;
37 int CountingClass::assign_count = 0;
38 
test_no_object_creation()39 void test_no_object_creation()
40 {
41   BOOST_TEST_EQ(0, CountingClass::count);
42   BOOST_TEST_EQ(0, CountingClass::assign_count);
43   {
44     CountingClass v1, v2;
45     optional<CountingClass&> oA(v1);
46     optional<CountingClass&> oB;
47     optional<CountingClass&> oC = oA;
48     oB = oA;
49     *oB = v2;
50     oC = none;
51     oC = optional<CountingClass&>(v2);
52     oB = none;
53     oA = oB;
54   }
55   BOOST_TEST_EQ(4, CountingClass::count);
56   BOOST_TEST_EQ(1, CountingClass::assign_count);
57 }
58 
59 template <typename T>
60 typename boost::enable_if< has_arrow<T> >::type
test_arrow_const()61 test_arrow_const()
62 {
63   const typename concrete_type_of<T>::type v(2);
64   optional<const T&> o(v);
65   BOOST_TEST(o);
66   BOOST_TEST_EQ(o->val(), 2);
67   BOOST_TEST(boost::addressof(o->val()) == boost::addressof(v.val()));
68 }
69 
70 template <typename T>
71 typename boost::disable_if< has_arrow<T> >::type
test_arrow_const()72 test_arrow_const()
73 {
74 }
75 
76 template <typename T>
77 typename boost::enable_if< has_arrow<T> >::type
test_arrow_noconst_const()78 test_arrow_noconst_const()
79 {
80   typename concrete_type_of<T>::type v(2);
81   optional<const T&> o(v);
82   BOOST_TEST(o);
83   BOOST_TEST_EQ(o->val(), 2);
84   BOOST_TEST(boost::addressof(o->val()) == boost::addressof(v.val()));
85 
86   v.val() = 1;
87   BOOST_TEST(o);
88   BOOST_TEST_EQ(o->val(), 1);
89   BOOST_TEST_EQ(v.val(), 1);
90   BOOST_TEST(boost::addressof(o->val()) == boost::addressof(v.val()));
91 }
92 
93 template <typename T>
94 typename boost::disable_if< has_arrow<T> >::type
test_arrow_noconst_const()95 test_arrow_noconst_const()
96 {
97 }
98 
99 template <typename T>
100 typename boost::enable_if< has_arrow<T> >::type
test_arrow()101 test_arrow()
102 {
103   typename concrete_type_of<T>::type v(2);
104   optional<T&> o(v);
105   BOOST_TEST(o);
106   BOOST_TEST_EQ(o->val(), 2);
107   BOOST_TEST(boost::addressof(o->val()) == boost::addressof(v.val()));
108 
109   v.val() = 1;
110   BOOST_TEST(o);
111   BOOST_TEST_EQ(o->val(), 1);
112   BOOST_TEST_EQ(v.val(), 1);
113   BOOST_TEST(boost::addressof(o->val()) == boost::addressof(v.val()));
114 
115   o->val() = 3;
116   BOOST_TEST(o);
117   BOOST_TEST_EQ(o->val(), 3);
118   BOOST_TEST_EQ(v.val(), 3);
119   BOOST_TEST(boost::addressof(o->val()) == boost::addressof(v.val()));
120 
121 }
122 
123 template <typename T>
124 typename boost::disable_if< has_arrow<T> >::type
test_arrow()125 test_arrow()
126 {
127 }
128 
129 template <typename T>
test_not_containing_value_for()130 void test_not_containing_value_for()
131 {
132   optional<T&> o1;
133   optional<T&> o2 = none;
134   optional<T&> o3 = o1;
135 
136   BOOST_TEST(!o1);
137   BOOST_TEST(!o2);
138   BOOST_TEST(!o3);
139 
140   BOOST_TEST(o1 == none);
141   BOOST_TEST(o2 == none);
142   BOOST_TEST(o3 == none);
143 }
144 
145 template <typename T>
test_direct_init_for_const()146 void test_direct_init_for_const()
147 {
148   const typename concrete_type_of<T>::type v(2);
149   optional<const T&> o(v);
150 
151   BOOST_TEST(o);
152   BOOST_TEST(o != none);
153   BOOST_TEST(boost::addressof(*o) == boost::addressof(v));
154   BOOST_TEST_EQ(val(*o), val(v));
155   BOOST_TEST_EQ(val(*o), 2);
156 }
157 
158 template <typename T>
test_direct_init_for_noconst_const()159 void test_direct_init_for_noconst_const()
160 {
161   typename concrete_type_of<T>::type v(2);
162   optional<const T&> o(v);
163 
164   BOOST_TEST(o);
165   BOOST_TEST(o != none);
166   BOOST_TEST(boost::addressof(*o) == boost::addressof(v));
167   BOOST_TEST_EQ(val(*o), val(v));
168   BOOST_TEST_EQ(val(*o), 2);
169 
170   val(v) = 9;
171   BOOST_TEST(boost::addressof(*o) == boost::addressof(v));
172   BOOST_TEST_EQ(val(*o), val(v));
173   BOOST_TEST_EQ(val(*o), 9);
174   BOOST_TEST_EQ(val(v), 9);
175 }
176 
177 template <typename T>
test_direct_init_for()178 void test_direct_init_for()
179 {
180   typename concrete_type_of<T>::type v(2);
181   optional<T&> o(v);
182 
183   BOOST_TEST(o);
184   BOOST_TEST(o != none);
185   BOOST_TEST(boost::addressof(*o) == boost::addressof(v));
186   BOOST_TEST_EQ(val(*o), val(v));
187   BOOST_TEST_EQ(val(*o), 2);
188 
189   val(v) = 9;
190   BOOST_TEST(boost::addressof(*o) == boost::addressof(v));
191   BOOST_TEST_EQ(val(*o), val(v));
192   BOOST_TEST_EQ(val(*o), 9);
193   BOOST_TEST_EQ(val(v), 9);
194 
195   val(*o) = 7;
196   BOOST_TEST(boost::addressof(*o) == boost::addressof(v));
197   BOOST_TEST_EQ(val(*o), val(v));
198   BOOST_TEST_EQ(val(*o), 7);
199   BOOST_TEST_EQ(val(v), 7);
200 }
201 
202 template <typename T, typename U>
test_clearing_the_value()203 void test_clearing_the_value()
204 {
205   typename concrete_type_of<T>::type v(2);
206   optional<U&> o1(v), o2(v);
207 
208   BOOST_TEST(o1);
209   BOOST_TEST(o1 != none);
210   BOOST_TEST(o2);
211   BOOST_TEST(o2 != none);
212 
213   o1 = none;
214   BOOST_TEST(!o1);
215   BOOST_TEST(o1 == none);
216   BOOST_TEST(o2);
217   BOOST_TEST(o2 != none);
218   BOOST_TEST_EQ(val(*o2), 2);
219   BOOST_TEST(boost::addressof(*o2) == boost::addressof(v));
220   BOOST_TEST_EQ(val(v), 2);
221 }
222 
223 template <typename T, typename U>
test_equality()224 void test_equality()
225 {
226   typename concrete_type_of<T>::type v1(1), v2(2), v2_(2), v3(3);
227   optional<U&> o1(v1), o2(v2), o2_(v2_), o3(v3), o3_(v3), oN, oN_;
228   // o2 and o2_ point to different objects; o3 and o3_ point to the same object
229 
230   BOOST_TEST(oN  == oN);
231   BOOST_TEST(oN  == oN_);
232   BOOST_TEST(oN_ == oN);
233   BOOST_TEST(o1  == o1);
234   BOOST_TEST(o2  == o2);
235   BOOST_TEST(o2  == o2_);
236   BOOST_TEST(o2_ == o2);
237   BOOST_TEST(o3  == o3);
238   BOOST_TEST(o3  == o3_);
239   BOOST_TEST(!(oN == o1));
240   BOOST_TEST(!(o1 == oN));
241   BOOST_TEST(!(o2 == o1));
242   BOOST_TEST(!(o2 == oN));
243 
244   BOOST_TEST(!(oN  != oN));
245   BOOST_TEST(!(oN  != oN_));
246   BOOST_TEST(!(oN_ != oN));
247   BOOST_TEST(!(o1  != o1));
248   BOOST_TEST(!(o2  != o2));
249   BOOST_TEST(!(o2  != o2_));
250   BOOST_TEST(!(o2_ != o2));
251   BOOST_TEST(!(o3  != o3));
252   BOOST_TEST(!(o3  != o3_));
253   BOOST_TEST( (oN  != o1));
254   BOOST_TEST( (o1  != oN));
255   BOOST_TEST( (o2  != o1));
256   BOOST_TEST( (o2  != oN));
257 }
258 
259 template <typename T, typename U>
test_order()260 void test_order()
261 {
262   typename concrete_type_of<T>::type v1(1), v2(2), v2_(2), v3(3);
263   optional<U&> o1(v1), o2(v2), o2_(v2_), o3(v3), o3_(v3), oN, oN_;
264   // o2 and o2_ point to different objects; o3 and o3_ point to the same object
265 
266   BOOST_TEST(!(oN  < oN));
267   BOOST_TEST(!(oN  < oN_));
268   BOOST_TEST(!(oN_ < oN));
269   BOOST_TEST(!(o1  < o1));
270   BOOST_TEST(!(o2  < o2));
271   BOOST_TEST(!(o2  < o2_));
272   BOOST_TEST(!(o2_ < o2));
273   BOOST_TEST(!(o3  < o3));
274   BOOST_TEST(!(o3  < o3_));
275 
276   BOOST_TEST( (oN  <= oN));
277   BOOST_TEST( (oN  <= oN_));
278   BOOST_TEST( (oN_ <= oN));
279   BOOST_TEST( (o1  <= o1));
280   BOOST_TEST( (o2  <= o2));
281   BOOST_TEST( (o2  <= o2_));
282   BOOST_TEST( (o2_ <= o2));
283   BOOST_TEST( (o3  <= o3));
284   BOOST_TEST( (o3  <= o3_));
285 
286   BOOST_TEST(!(oN  > oN));
287   BOOST_TEST(!(oN  > oN_));
288   BOOST_TEST(!(oN_ > oN));
289   BOOST_TEST(!(o1  > o1));
290   BOOST_TEST(!(o2  > o2));
291   BOOST_TEST(!(o2  > o2_));
292   BOOST_TEST(!(o2_ > o2));
293   BOOST_TEST(!(o3  > o3));
294   BOOST_TEST(!(o3  > o3_));
295 
296   BOOST_TEST( (oN  >= oN));
297   BOOST_TEST( (oN  >= oN_));
298   BOOST_TEST( (oN_ >= oN));
299   BOOST_TEST( (o1  >= o1));
300   BOOST_TEST( (o2  >= o2));
301   BOOST_TEST( (o2  >= o2_));
302   BOOST_TEST( (o2_ >= o2));
303   BOOST_TEST( (o3  >= o3));
304   BOOST_TEST( (o3  >= o3_));
305 
306   BOOST_TEST( (oN  < o1));
307   BOOST_TEST( (oN_ < o1));
308   BOOST_TEST( (oN  < o2));
309   BOOST_TEST( (oN_ < o2));
310   BOOST_TEST( (oN  < o2_));
311   BOOST_TEST( (oN_ < o2_));
312   BOOST_TEST( (oN  < o3));
313   BOOST_TEST( (oN_ < o3));
314   BOOST_TEST( (oN  < o3_));
315   BOOST_TEST( (oN_ < o3_));
316   BOOST_TEST( (o1  < o2));
317   BOOST_TEST( (o1  < o2_));
318   BOOST_TEST( (o1  < o3));
319   BOOST_TEST( (o1  < o3_));
320   BOOST_TEST( (o2  < o3));
321   BOOST_TEST( (o2_ < o3));
322   BOOST_TEST( (o2  < o3_));
323   BOOST_TEST( (o2_ < o3_));
324 
325   BOOST_TEST( (oN  <= o1));
326   BOOST_TEST( (oN_ <= o1));
327   BOOST_TEST( (oN  <= o2));
328   BOOST_TEST( (oN_ <= o2));
329   BOOST_TEST( (oN  <= o2_));
330   BOOST_TEST( (oN_ <= o2_));
331   BOOST_TEST( (oN  <= o3));
332   BOOST_TEST( (oN_ <= o3));
333   BOOST_TEST( (oN  <= o3_));
334   BOOST_TEST( (oN_ <= o3_));
335   BOOST_TEST( (o1  <= o2));
336   BOOST_TEST( (o1  <= o2_));
337   BOOST_TEST( (o1  <= o3));
338   BOOST_TEST( (o1  <= o3_));
339   BOOST_TEST( (o2  <= o3));
340   BOOST_TEST( (o2_ <= o3));
341   BOOST_TEST( (o2  <= o3_));
342   BOOST_TEST( (o2_ <= o3_));
343 
344   BOOST_TEST(!(oN  > o1));
345   BOOST_TEST(!(oN_ > o1));
346   BOOST_TEST(!(oN  > o2));
347   BOOST_TEST(!(oN_ > o2));
348   BOOST_TEST(!(oN  > o2_));
349   BOOST_TEST(!(oN_ > o2_));
350   BOOST_TEST(!(oN  > o3));
351   BOOST_TEST(!(oN_ > o3));
352   BOOST_TEST(!(oN  > o3_));
353   BOOST_TEST(!(oN_ > o3_));
354   BOOST_TEST(!(o1  > o2));
355   BOOST_TEST(!(o1  > o2_));
356   BOOST_TEST(!(o1  > o3));
357   BOOST_TEST(!(o1  > o3_));
358   BOOST_TEST(!(o2  > o3));
359   BOOST_TEST(!(o2_ > o3));
360   BOOST_TEST(!(o2  > o3_));
361   BOOST_TEST(!(o2_ > o3_));
362 
363   BOOST_TEST(!(oN  >= o1));
364   BOOST_TEST(!(oN_ >= o1));
365   BOOST_TEST(!(oN  >= o2));
366   BOOST_TEST(!(oN_ >= o2));
367   BOOST_TEST(!(oN  >= o2_));
368   BOOST_TEST(!(oN_ >= o2_));
369   BOOST_TEST(!(oN  >= o3));
370   BOOST_TEST(!(oN_ >= o3));
371   BOOST_TEST(!(oN  >= o3_));
372   BOOST_TEST(!(oN_ >= o3_));
373   BOOST_TEST(!(o1  >= o2));
374   BOOST_TEST(!(o1  >= o2_));
375   BOOST_TEST(!(o1  >= o3));
376   BOOST_TEST(!(o1  >= o3_));
377   BOOST_TEST(!(o2  >= o3));
378   BOOST_TEST(!(o2_ >= o3));
379   BOOST_TEST(!(o2  >= o3_));
380   BOOST_TEST(!(o2_ >= o3_));
381 
382   BOOST_TEST(!(o1  < oN));
383   BOOST_TEST(!(o1  < oN_));
384   BOOST_TEST(!(o2  < oN));
385   BOOST_TEST(!(o2  < oN_));
386   BOOST_TEST(!(o2_ < oN));
387   BOOST_TEST(!(o2_ < oN_));
388   BOOST_TEST(!(o3  < oN));
389   BOOST_TEST(!(o3  < oN_));
390   BOOST_TEST(!(o3_ < oN));
391   BOOST_TEST(!(o3_ < oN_));
392   BOOST_TEST(!(o2  < oN));
393   BOOST_TEST(!(o2_ < oN_));
394   BOOST_TEST(!(o3  < oN));
395   BOOST_TEST(!(o3_ < oN_));
396   BOOST_TEST(!(o3  < oN));
397   BOOST_TEST(!(o3  < oN_));
398   BOOST_TEST(!(o3_ < oN));
399   BOOST_TEST(!(o3_ < oN_));
400 }
401 
402 template <typename T, typename U>
test_swap()403 void test_swap()
404 {
405   typename concrete_type_of<T>::type v1(1), v2(2);
406   optional<U&> o1(v1), o1_(v1), o2(v2), o2_(v2), oN, oN_;
407 
408   swap(o1, o1);
409   BOOST_TEST(o1);
410   BOOST_TEST(boost::addressof(*o1) == boost::addressof(v1));
411 
412   swap(oN, oN_);
413   BOOST_TEST(!oN);
414   BOOST_TEST(!oN_);
415 
416   swap(o1, oN);
417   BOOST_TEST(!o1);
418   BOOST_TEST(oN);
419   BOOST_TEST(boost::addressof(*oN) == boost::addressof(v1));
420 
421   swap(oN, o1);
422   BOOST_TEST(!oN);
423   BOOST_TEST(o1);
424   BOOST_TEST(boost::addressof(*o1) == boost::addressof(v1));
425 
426   swap(o1_, o2_);
427   BOOST_TEST(o1_);
428   BOOST_TEST(o2_);
429   BOOST_TEST(boost::addressof(*o1_) == boost::addressof(v2));
430   BOOST_TEST(boost::addressof(*o2_) == boost::addressof(v1));
431 }
432 
433 template <typename T, typename U>
test_convertability_of_compatible_reference_types()434 void test_convertability_of_compatible_reference_types()
435 {
436   typename concrete_type_of<T>::type v1(1);
437   optional<T&> oN, o1(v1);
438   optional<U&> uN(oN), u1(o1);
439   BOOST_TEST(!uN);
440   BOOST_TEST(u1);
441   BOOST_TEST(boost::addressof(*u1) == boost::addressof(*o1));
442 
443   uN = o1;
444   u1 = oN;
445   BOOST_TEST(!u1);
446   BOOST_TEST(uN);
447   BOOST_TEST(boost::addressof(*uN) == boost::addressof(*o1));
448 }
449 
450 template <typename T>
test_optional_ref()451 void test_optional_ref()
452 {
453   test_not_containing_value_for<T>();
454   test_direct_init_for<T>();
455   test_clearing_the_value<T, T>();
456   test_arrow<T>();
457   test_equality<T, T>();
458   test_order<T, T>();
459   test_swap<T, T>();
460 }
461 
462 template <typename T>
test_optional_const_ref()463 void test_optional_const_ref()
464 {
465   test_not_containing_value_for<const T>();
466   test_direct_init_for_const<T>();
467   test_direct_init_for_noconst_const<T>();
468   test_clearing_the_value<const T, const T>();
469   test_clearing_the_value<T, const T>();
470   test_arrow_const<T>();
471   test_arrow_noconst_const<T>();
472   test_equality<const T, const T>();
473   test_equality<T, const T>();
474   test_order<const T, const T>();
475   test_order<T, const T>();
476   test_swap<const T, const T>();
477   test_swap<T, const T>();
478 }
479 
main()480 int main()
481 {
482   test_optional_ref<int>();
483   test_optional_ref<ScopeGuard>();
484   test_optional_ref<Abstract>();
485   test_optional_ref< optional<int> >();
486 
487   test_optional_const_ref<int>();
488   test_optional_const_ref<ScopeGuard>();
489   test_optional_const_ref<Abstract>();
490   test_optional_const_ref< optional<int> >();
491 
492   test_convertability_of_compatible_reference_types<int, const int>();
493   test_convertability_of_compatible_reference_types<Impl, Abstract>();
494   test_convertability_of_compatible_reference_types<Impl, const Abstract>();
495   test_convertability_of_compatible_reference_types<const Impl, const Abstract>();
496   test_convertability_of_compatible_reference_types<optional<int>, const optional<int> >();
497 
498   return boost::report_errors();
499 }
500