• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2014 - 2015 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:
10 //  akrzemi1@gmail.com
11 
12 
13 #include "boost/optional/optional.hpp"
14 
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18 
19 #include "boost/core/lightweight_test.hpp"
20 
21 using boost::optional;
22 using boost::none;
23 
24 //#ifndef BOOST_OPTIONAL_NO_CONVERTING_ASSIGNMENT
25 //#ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR
26 
27 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
28 
29 enum State
30 {
31     sDefaultConstructed,
32     sValueCopyConstructed,
33     sValueMoveConstructed,
34     sCopyConstructed,
35     sMoveConstructed,
36     sMoveAssigned,
37     sCopyAssigned,
38     sValueCopyAssigned,
39     sValueMoveAssigned,
40     sMovedFrom,
41     sIntConstructed
42 };
43 
44 struct OracleVal
45 {
46     State s;
47     int i;
OracleValOracleVal48     OracleVal(int i = 0) : s(sIntConstructed), i(i) {}
49 };
50 
51 
52 struct Oracle
53 {
54     State s;
55     OracleVal val;
56 
OracleOracle57     Oracle() : s(sDefaultConstructed) {}
OracleOracle58     Oracle(const OracleVal& v) : s(sValueCopyConstructed), val(v) {}
OracleOracle59     Oracle(OracleVal&& v) : s(sValueMoveConstructed), val(std::move(v)) {v.s = sMovedFrom;}
OracleOracle60     Oracle(const Oracle& o) : s(sCopyConstructed), val(o.val) {}
OracleOracle61     Oracle(Oracle&& o) : s(sMoveConstructed), val(std::move(o.val)) {o.s = sMovedFrom;}
62 
operator =Oracle63     Oracle& operator=(const OracleVal& v) { s = sValueCopyAssigned; val = v; return *this; }
operator =Oracle64     Oracle& operator=(OracleVal&& v) { s = sValueMoveAssigned; val = std::move(v); v.s = sMovedFrom; return *this; }
operator =Oracle65     Oracle& operator=(const Oracle& o) { s = sCopyAssigned; val = o.val; return *this; }
operator =Oracle66     Oracle& operator=(Oracle&& o) { s = sMoveAssigned; val = std::move(o.val); o.s = sMovedFrom; return *this; }
67 };
68 
operator ==(Oracle const & a,Oracle const & b)69 bool operator==( Oracle const& a, Oracle const& b ) { return a.val.i == b.val.i; }
operator !=(Oracle const & a,Oracle const & b)70 bool operator!=( Oracle const& a, Oracle const& b ) { return a.val.i != b.val.i; }
71 
72 
test_move_ctor_from_U()73 void test_move_ctor_from_U()
74 {
75   optional<Oracle> o1 ((OracleVal()));
76   BOOST_TEST(o1);
77   BOOST_TEST(o1->s == sValueMoveConstructed || o1->s == sMoveConstructed);
78 
79   OracleVal v1;
80   optional<Oracle> o2 (v1);
81   BOOST_TEST(o2);
82   BOOST_TEST(o2->s == sValueCopyConstructed || o2->s == sCopyConstructed || o2->s == sMoveConstructed );
83   BOOST_TEST(v1.s == sIntConstructed);
84 
85   optional<Oracle> o3 (boost::move(v1));
86   BOOST_TEST(o3);
87   BOOST_TEST(o3->s == sValueMoveConstructed || o3->s == sMoveConstructed);
88   BOOST_TEST(v1.s == sMovedFrom);
89 }
90 
test_move_ctor_form_T()91 void test_move_ctor_form_T()
92 {
93   optional<Oracle> o1 ((Oracle()));
94   BOOST_TEST(o1);
95   BOOST_TEST(o1->s == sMoveConstructed);
96 
97   Oracle v1;
98   optional<Oracle> o2 (v1);
99   BOOST_TEST(o2);
100   BOOST_TEST(o2->s == sCopyConstructed);
101   BOOST_TEST(v1.s == sDefaultConstructed);
102 
103   optional<Oracle> o3 (boost::move(v1));
104   BOOST_TEST(o3);
105   BOOST_TEST(o3->s == sMoveConstructed);
106   BOOST_TEST(v1.s == sMovedFrom);
107 }
108 
test_move_ctor_from_optional_T()109 void test_move_ctor_from_optional_T()
110 {
111   optional<Oracle> o1;
112   optional<Oracle> o2(boost::move(o1));
113 
114   BOOST_TEST(!o1);
115   BOOST_TEST(!o2);
116 
117   optional<Oracle> o3((Oracle()));
118   optional<Oracle> o4(boost::move(o3));
119   BOOST_TEST(o3);
120   BOOST_TEST(o4);
121   BOOST_TEST(o3->s == sMovedFrom);
122   BOOST_TEST(o4->s == sMoveConstructed);
123 
124   optional<Oracle> o5((optional<Oracle>()));
125   BOOST_TEST(!o5);
126 
127   optional<Oracle> o6((optional<Oracle>(Oracle())));
128   BOOST_TEST(o6);
129   BOOST_TEST(o6->s == sMoveConstructed);
130 
131   optional<Oracle> o7(o6); // does copy ctor from non-const lvalue compile?
132 }
133 
test_move_assign_from_U()134 void test_move_assign_from_U()
135 {
136   optional<Oracle> o1 = boost::none; // test if additional ctors didn't break it
137   o1 = boost::none;                  // test if additional assignments didn't break it
138   o1 = OracleVal();
139   BOOST_TEST(o1);
140 
141   BOOST_TEST(o1->s == sValueMoveConstructed);
142 
143   o1 = OracleVal();
144   BOOST_TEST(o1);
145   BOOST_TEST(o1->s == sMoveAssigned);
146 
147   OracleVal v1;
148   optional<Oracle> o2;
149   o2 = v1;
150   BOOST_TEST(o2);
151   BOOST_TEST(o2->s == sValueCopyConstructed);
152   BOOST_TEST(v1.s == sIntConstructed);
153   o2 = v1;
154   BOOST_TEST(o2);
155   BOOST_TEST(o2->s == sCopyAssigned || o2->s == sMoveAssigned);
156   BOOST_TEST(v1.s == sIntConstructed);
157 
158   optional<Oracle> o3;
159   o3 = boost::move(v1);
160   BOOST_TEST(o3);
161   BOOST_TEST(o3->s == sValueMoveConstructed);
162   BOOST_TEST(v1.s == sMovedFrom);
163 }
164 
test_move_assign_from_T()165 void test_move_assign_from_T()
166 {
167   optional<Oracle> o1;
168   o1 = Oracle();
169   BOOST_TEST(o1);
170   BOOST_TEST(o1->s == sMoveConstructed);
171 
172   o1 = Oracle();
173   BOOST_TEST(o1);
174   BOOST_TEST(o1->s == sMoveAssigned);
175 
176   Oracle v1;
177   optional<Oracle> o2;
178   o2 = v1;
179   BOOST_TEST(o2);
180   BOOST_TEST(o2->s == sCopyConstructed);
181   BOOST_TEST(v1.s == sDefaultConstructed);
182   o2 = v1;
183   BOOST_TEST(o2);
184   BOOST_TEST(o2->s == sCopyAssigned);
185   BOOST_TEST(v1.s == sDefaultConstructed);
186 
187   optional<Oracle> o3;
188   o3 = boost::move(v1);
189   BOOST_TEST(o3);
190   BOOST_TEST(o3->s == sMoveConstructed);
191   BOOST_TEST(v1.s == sMovedFrom);
192 }
193 
test_move_assign_from_optional_T()194 void test_move_assign_from_optional_T()
195 {
196     optional<Oracle> o1;
197     optional<Oracle> o2;
198     o1 = optional<Oracle>();
199     BOOST_TEST(!o1);
200     optional<Oracle> o3((Oracle()));
201     o1 = o3;
202     BOOST_TEST(o3);
203     BOOST_TEST(o3->s == sMoveConstructed);
204     BOOST_TEST(o1);
205     BOOST_TEST(o1->s == sCopyConstructed);
206 
207     o2 = boost::move(o3);
208     BOOST_TEST(o3);
209     BOOST_TEST(o3->s == sMovedFrom);
210     BOOST_TEST(o2);
211     BOOST_TEST(o2->s == sMoveConstructed);
212 
213     o2 = optional<Oracle>((Oracle()));
214     BOOST_TEST(o2);
215     BOOST_TEST(o2->s == sMoveAssigned);
216 }
217 
218 class MoveOnly
219 {
220 public:
221   int val;
MoveOnly(int v)222   MoveOnly(int v) : val(v) {}
MoveOnly(MoveOnly && rhs)223   MoveOnly(MoveOnly&& rhs) : val(rhs.val) { rhs.val = 0; }
operator =(MoveOnly && rhs)224   void operator=(MoveOnly&& rhs) {val = rhs.val; rhs.val = 0; }
225 
226 private:
227   MoveOnly(MoveOnly const&);
228   void operator=(MoveOnly const&);
229 
230   friend class MoveOnlyB;
231 };
232 
test_with_move_only()233 void test_with_move_only()
234 {
235     optional<MoveOnly> o1;
236     optional<MoveOnly> o2((MoveOnly(1)));
237     BOOST_TEST(o2);
238     BOOST_TEST(o2->val == 1);
239     optional<MoveOnly> o3 (boost::move(o1));
240     BOOST_TEST(!o3);
241     optional<MoveOnly> o4 (boost::move(o2));
242     BOOST_TEST(o4);
243     BOOST_TEST(o4->val == 1);
244     BOOST_TEST(o2);
245     BOOST_TEST(o2->val == 0);
246 
247     o3 = boost::move(o4);
248     BOOST_TEST(o3);
249     BOOST_TEST(o3->val == 1);
250     BOOST_TEST(o4);
251     BOOST_TEST(o4->val == 0);
252 }
253 
254 class MoveOnlyB
255 {
256 public:
257   int val;
MoveOnlyB(int v)258   MoveOnlyB(int v) : val(v) {}
MoveOnlyB(MoveOnlyB && rhs)259   MoveOnlyB(MoveOnlyB&& rhs) : val(rhs.val) { rhs.val = 0; }
operator =(MoveOnlyB && rhs)260   void operator=(MoveOnlyB&& rhs) {val = rhs.val; rhs.val = 0; }
MoveOnlyB(MoveOnly && rhs)261   MoveOnlyB(MoveOnly&& rhs) : val(rhs.val) { rhs.val = 0; }
operator =(MoveOnly && rhs)262   void operator=(MoveOnly&& rhs) {val = rhs.val; rhs.val = 0; }
263 
264 private:
265   MoveOnlyB(MoveOnlyB const&);
266   void operator=(MoveOnlyB const&);
267   MoveOnlyB(MoveOnly const&);
268   void operator=(MoveOnly const&);
269 };
270 
test_move_assign_from_optional_U()271 void test_move_assign_from_optional_U()
272 {
273     optional<MoveOnly> a((MoveOnly(2)));
274     optional<MoveOnlyB> b1;
275     b1 = boost::move(a);
276 
277     BOOST_TEST(b1);
278     BOOST_TEST(b1->val == 2);
279     BOOST_TEST(a);
280     BOOST_TEST(a->val == 0);
281 
282     b1 = MoveOnly(4);
283 
284     BOOST_TEST(b1);
285     BOOST_TEST(b1->val == 4);
286 }
287 
test_move_ctor_from_optional_U()288 void test_move_ctor_from_optional_U()
289 {
290     optional<MoveOnly> a((MoveOnly(2)));
291     optional<MoveOnlyB> b1(boost::move(a));
292 
293     BOOST_TEST(b1);
294     BOOST_TEST(b1->val == 2);
295     BOOST_TEST(a);
296     BOOST_TEST(a->val == 0);
297 
298     optional<MoveOnlyB> b2(( optional<MoveOnly>(( MoveOnly(4) )) ));
299 
300     BOOST_TEST(b2);
301     BOOST_TEST(b2->val == 4);
302 }
303 
test_swap()304 void test_swap()
305 {
306     optional<MoveOnly> a((MoveOnly(2)));
307     optional<MoveOnly> b((MoveOnly(3)));
308     swap(a, b);
309 
310     BOOST_TEST(a->val == 3);
311     BOOST_TEST(b->val == 2);
312 }
313 
test_optional_ref_to_movables()314 void test_optional_ref_to_movables()
315 {
316     MoveOnly m(3);
317     optional<MoveOnly&> orm = m;
318     orm->val = 2;
319     BOOST_TEST(m.val == 2);
320 
321     optional<MoveOnly&> orm2 = orm;
322     orm2->val = 1;
323     BOOST_TEST(m.val == 1);
324     BOOST_TEST(orm->val == 1);
325 
326     optional<MoveOnly&> orm3 = boost::move(orm);
327     orm3->val = 4;
328     BOOST_TEST(m.val == 4);
329     BOOST_TEST(orm->val == 4);
330     BOOST_TEST(orm2->val == 4);
331 }
332 
333 #endif
334 
main()335 int main()
336 {
337 #ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
338     test_move_ctor_from_U();
339     test_move_ctor_form_T();
340     test_move_ctor_from_optional_T();
341     test_move_ctor_from_optional_U();
342     test_move_assign_from_U();
343     test_move_assign_from_T();
344     test_move_assign_from_optional_T();
345     test_move_assign_from_optional_U();
346     test_with_move_only();
347     test_optional_ref_to_movables();
348     test_swap();
349 #endif
350 
351   return boost::report_errors();
352 }
353