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:
10 //  [email protected]
11 
12 #include "boost/optional/optional.hpp"
13 
14 #ifdef BOOST_BORLANDC
15 #pragma hdrstop
16 #endif
17 
18 #include <string>
19 #include "boost/core/lightweight_test.hpp"
20 #include "boost/none.hpp"
21 
22 //#ifndef BOOST_OPTIONAL_NO_CONVERTING_ASSIGNMENT
23 //#ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR
24 
25 using boost::optional;
26 using boost::none;
27 using boost::in_place_init;
28 using boost::in_place_init_if;
29 
30 #if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES)
31 
32 class Guard
33 {
34 public:
35     int which_ctor;
Guard()36     Guard () : which_ctor(0) { }
Guard(int &,double &&)37     Guard (int&, double&&) : which_ctor(1) { }
Guard(int &&,double &)38     Guard (int&&, double&) : which_ctor(2) { }
Guard(int &&,double &&)39     Guard (int&&, double&&) : which_ctor(3) { }
Guard(int &,double &)40     Guard (int&, double&) : which_ctor(4) { }
Guard(std::string const &)41     Guard (std::string const&) : which_ctor(5) { }
Guard(std::string &)42     Guard (std::string &) : which_ctor(6) { }
Guard(std::string &&)43     Guard (std::string &&) : which_ctor(7) { }
44 private:
45     Guard(Guard&&);
46     Guard(Guard const&);
47     void operator=(Guard &&);
48     void operator=(Guard const&);
49 };
50 
51 
test_emplace()52 void test_emplace()
53 {
54     int i = 0;
55     double d = 0.0;
56     const std::string cs;
57     std::string ms;
58     optional<Guard> o;
59 
60     o.emplace();
61     BOOST_TEST(o);
62     BOOST_TEST(0 == o->which_ctor);
63 
64     o.emplace(i, 2.0);
65     BOOST_TEST(o);
66     BOOST_TEST(1 == o->which_ctor);
67 
68     o.emplace(1, d);
69     BOOST_TEST(o);
70     BOOST_TEST(2 == o->which_ctor);
71 
72     o.emplace(1, 2.0);
73     BOOST_TEST(o);
74     BOOST_TEST(3 == o->which_ctor);
75 
76     o.emplace(i, d);
77     BOOST_TEST(o);
78     BOOST_TEST(4 == o->which_ctor);
79 
80     o.emplace(cs);
81     BOOST_TEST(o);
82     BOOST_TEST(5 == o->which_ctor);
83 
84     o.emplace(ms);
85     BOOST_TEST(o);
86     BOOST_TEST(6 == o->which_ctor);
87 
88     o.emplace(std::string());
89     BOOST_TEST(o);
90     BOOST_TEST(7 == o->which_ctor);
91 }
92 
test_in_place_ctor()93 void test_in_place_ctor()
94 {
95     int i = 0;
96     double d = 0.0;
97     const std::string cs;
98     std::string ms;
99 
100   {
101     optional<Guard> o (in_place_init);
102     BOOST_TEST(o);
103     BOOST_TEST(0 == o->which_ctor);
104   }
105   {
106     optional<Guard> o (in_place_init, i, 2.0);
107     BOOST_TEST(o);
108     BOOST_TEST(1 == o->which_ctor);
109   }
110   {
111     optional<Guard> o (in_place_init, 1, d);
112     BOOST_TEST(o);
113     BOOST_TEST(2 == o->which_ctor);
114   }
115   {
116     optional<Guard> o (in_place_init, 1, 2.0);
117     BOOST_TEST(o);
118     BOOST_TEST(3 == o->which_ctor);
119   }
120   {
121     optional<Guard> o (in_place_init, i, d);
122     BOOST_TEST(o);
123     BOOST_TEST(4 == o->which_ctor);
124   }
125   {
126     optional<Guard> o (in_place_init, cs);
127     BOOST_TEST(o);
128     BOOST_TEST(5 == o->which_ctor);
129   }
130   {
131     optional<Guard> o (in_place_init, ms);
132     BOOST_TEST(o);
133     BOOST_TEST(6 == o->which_ctor);
134   }
135   {
136     optional<Guard> o (in_place_init, std::string());
137     BOOST_TEST(o);
138     BOOST_TEST(7 == o->which_ctor);
139   }
140 }
141 
test_in_place_if_ctor()142 void test_in_place_if_ctor()
143 {
144     int i = 0;
145     double d = 0.0;
146     const std::string cs;
147     std::string ms;
148 
149   {
150     optional<Guard> o (in_place_init_if, true);
151     BOOST_TEST(o);
152     BOOST_TEST(0 == o->which_ctor);
153   }
154   {
155     optional<Guard> o (in_place_init_if, true, i, 2.0);
156     BOOST_TEST(o);
157     BOOST_TEST(1 == o->which_ctor);
158   }
159   {
160     optional<Guard> o (in_place_init_if, true, 1, d);
161     BOOST_TEST(o);
162     BOOST_TEST(2 == o->which_ctor);
163   }
164   {
165     optional<Guard> o (in_place_init_if, true, 1, 2.0);
166     BOOST_TEST(o);
167     BOOST_TEST(3 == o->which_ctor);
168   }
169   {
170     optional<Guard> o (in_place_init_if, true, i, d);
171     BOOST_TEST(o);
172     BOOST_TEST(4 == o->which_ctor);
173   }
174   {
175     optional<Guard> o (in_place_init_if, true, cs);
176     BOOST_TEST(o);
177     BOOST_TEST(5 == o->which_ctor);
178   }
179   {
180     optional<Guard> o (in_place_init_if, true, ms);
181     BOOST_TEST(o);
182     BOOST_TEST(6 == o->which_ctor);
183   }
184   {
185     optional<Guard> o (in_place_init_if, true, std::string());
186     BOOST_TEST(o);
187     BOOST_TEST(7 == o->which_ctor);
188   }
189 
190   {
191     optional<Guard> o (in_place_init_if, false, 1, 2.0);
192     BOOST_TEST(!o);
193   }
194 }
195 
196 
197 #endif
198 
199 #if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
200 
201 
202 struct ThrowOnMove
203 {
ThrowOnMoveThrowOnMove204     ThrowOnMove(ThrowOnMove&&) { throw int(); }
ThrowOnMoveThrowOnMove205     ThrowOnMove(ThrowOnMove const&) { throw int(); }
ThrowOnMoveThrowOnMove206     ThrowOnMove(int){}
207 };
208 
209 
test_no_moves_on_emplacement()210 void test_no_moves_on_emplacement()
211 {
212     try {
213         optional<ThrowOnMove> o;
214         o.emplace(1);
215         BOOST_TEST(o);
216     }
217     catch (...) {
218         BOOST_TEST(false);
219     }
220 }
221 
test_no_moves_on_in_place_ctor()222 void test_no_moves_on_in_place_ctor()
223 {
224     try {
225         optional<ThrowOnMove> o (in_place_init, 1);
226         BOOST_TEST(o);
227 
228         optional<ThrowOnMove> p (in_place_init_if, true, 1);
229         BOOST_TEST(p);
230 
231         optional<ThrowOnMove> q (in_place_init_if, false, 1);
232         BOOST_TEST(!q);
233     }
234     catch (...) {
235         BOOST_TEST(false);
236     }
237 }
238 
239 #endif
240 
241 struct Thrower
242 {
ThrowerThrower243     Thrower(bool throw_) { if (throw_) throw int(); }
244 
245 private:
246     Thrower(Thrower const&);
247 #if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
248     Thrower(Thrower&&);
249 #endif
250 };
251 
test_clear_on_throw()252 void test_clear_on_throw()
253 {
254     optional<Thrower> ot;
255     try {
256         ot.emplace(false);
257         BOOST_TEST(ot);
258     } catch(...) {
259         BOOST_TEST(false);
260     }
261 
262     try {
263         ot.emplace(true);
264         BOOST_TEST(false);
265     } catch(...) {
266         BOOST_TEST(!ot);
267     }
268 }
269 
test_no_assignment_on_emplacement()270 void test_no_assignment_on_emplacement()
271 {
272     optional<const std::string> os, ot;
273     BOOST_TEST(!os);
274     os.emplace("wow");
275     BOOST_TEST(os);
276     BOOST_TEST_EQ(*os, "wow");
277 
278     BOOST_TEST(!ot);
279     ot.emplace();
280     BOOST_TEST(ot);
281     BOOST_TEST_EQ(*ot, "");
282 }
283 
284 namespace no_rvalue_refs {
285 
286 class Guard
287 {
288 public:
289     int which_ctor;
Guard()290     Guard () : which_ctor(0) { }
Guard(std::string const &)291     Guard (std::string const&) : which_ctor(5) { }
Guard(std::string &)292     Guard (std::string &) : which_ctor(6) { }
293 private:
294     Guard(Guard const&);
295     void operator=(Guard const&);
296 };
297 
test_emplace()298 void test_emplace()
299 {
300     const std::string cs;
301     std::string ms;
302     optional<Guard> o;
303 
304     o.emplace();
305     BOOST_TEST(o);
306     BOOST_TEST(0 == o->which_ctor);
307 
308     o.emplace(cs);
309     BOOST_TEST(o);
310     BOOST_TEST(5 == o->which_ctor);
311 
312     o.emplace(ms);
313     BOOST_TEST(o);
314     BOOST_TEST(6 == o->which_ctor);
315 }
316 
test_in_place_ctor()317 void test_in_place_ctor()
318 {
319   const std::string cs;
320   std::string ms;
321 
322   {
323     optional<Guard> o (in_place_init);
324     BOOST_TEST(o);
325     BOOST_TEST(0 == o->which_ctor);
326   }
327   {
328     optional<Guard> o (in_place_init, cs);
329     BOOST_TEST(o);
330     BOOST_TEST(5 == o->which_ctor);
331   }
332   {
333     optional<Guard> o (in_place_init, ms);
334     BOOST_TEST(o);
335     BOOST_TEST(6 == o->which_ctor);
336   }
337 }
338 
test_in_place_if_ctor()339 void test_in_place_if_ctor()
340 {
341   const std::string cs;
342   std::string ms;
343 
344   {
345     optional<Guard> n (in_place_init_if, false);
346     BOOST_TEST(!n);
347 
348     optional<Guard> o (in_place_init_if, true);
349     BOOST_TEST(o);
350     BOOST_TEST(0 == o->which_ctor);
351   }
352   {
353     optional<Guard> n (in_place_init_if, false, cs);
354     BOOST_TEST(!n);
355 
356     optional<Guard> o (in_place_init_if, true, cs);
357     BOOST_TEST(o);
358     BOOST_TEST(5 == o->which_ctor);
359   }
360   {
361     optional<Guard> n (in_place_init_if, false, ms);
362     BOOST_TEST(!n);
363 
364     optional<Guard> o (in_place_init_if, true, ms);
365     BOOST_TEST(o);
366     BOOST_TEST(6 == o->which_ctor);
367   }
368 }
369 
370 } // namespace no_rvalue_ref
371 
main()372 int main()
373 {
374 #if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) && (!defined BOOST_NO_CXX11_VARIADIC_TEMPLATES)
375     test_emplace();
376     test_in_place_ctor();
377     test_in_place_if_ctor();
378 #endif
379 #if (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
380     test_no_moves_on_emplacement();
381     test_no_moves_on_in_place_ctor();
382 #endif
383     test_clear_on_throw();
384     test_no_assignment_on_emplacement();
385     no_rvalue_refs::test_emplace();
386     no_rvalue_refs::test_in_place_ctor();
387     no_rvalue_refs::test_in_place_if_ctor();
388 
389     return boost::report_errors();
390 }
391