1 // Copyright (C) 2011 - 2012 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 // The idea and interface is based on Boost.Optional library
8 // authored by Fernando Luis Cacciola Carballal
9 
10 # include "optional.hpp"
11 # include <vector>
12 # include <iostream>
13 # include <functional>
14 # include <complex>
15 
16 
17 
18 struct caller {
callercaller19     template <class T> caller(T fun) { fun(); }
20 };
21 # define CAT2(X, Y) X ## Y
22 # define CAT(X, Y) CAT2(X, Y)
23 # define TEST(NAME) caller CAT(__VAR, __LINE__) = []
24 
25 enum  State
26 {
27     sDefaultConstructed,
28     sValueCopyConstructed,
29     sValueMoveConstructed,
30     sCopyConstructed,
31     sMoveConstructed,
32     sMoveAssigned,
33     sCopyAssigned,
34     sValueCopyAssigned,
35     sValueMoveAssigned,
36     sMovedFrom,
37     sValueConstructed
38 };
39 
40 struct OracleVal
41 {
42     State s;
43     int i;
OracleValOracleVal44     OracleVal(int i = 0) : s(sValueConstructed), i(i) {}
45 };
46 
47 struct Oracle
48 {
49     State s;
50     OracleVal val;
51 
OracleOracle52     Oracle() : s(sDefaultConstructed) {}
OracleOracle53     Oracle(const OracleVal& v) : s(sValueCopyConstructed), val(v) {}
OracleOracle54     Oracle(OracleVal&& v) : s(sValueMoveConstructed), val(std::move(v)) {v.s = sMovedFrom;}
OracleOracle55     Oracle(const Oracle& o) : s(sCopyConstructed), val(o.val) {}
OracleOracle56     Oracle(Oracle&& o) : s(sMoveConstructed), val(std::move(o.val)) {o.s = sMovedFrom;}
57 
operator =Oracle58     Oracle& operator=(const OracleVal& v) { s = sValueCopyConstructed; val = v; return *this; }
operator =Oracle59     Oracle& operator=(OracleVal&& v) { s = sValueMoveConstructed; val = std::move(v); v.s = sMovedFrom; return *this; }
operator =Oracle60     Oracle& operator=(const Oracle& o) { s = sCopyConstructed; val = o.val; return *this; }
operator =Oracle61     Oracle& operator=(Oracle&& o) { s = sMoveConstructed; val = std::move(o.val); o.s = sMovedFrom; return *this; }
62 };
63 
64 struct Guard
65 {
66     std::string val;
GuardGuard67     Guard() : val{} {}
GuardGuard68     explicit Guard(std::string s, int = 0) : val(s) {}
69     Guard(const Guard&) = delete;
70     Guard(Guard&&) = delete;
71     void operator=(const Guard&) = delete;
72     void operator=(Guard&&) = delete;
73 };
74 
75 struct ExplicitStr
76 {
77     std::string s;
ExplicitStrExplicitStr78     explicit ExplicitStr(const char* chp) : s(chp) {};
79 };
80 
81 struct Date
82 {
83     int i;
84     Date() = delete;
DateDate85     Date(int i) : i{i} {};
DateDate86     Date(Date&& d) : i(d.i) { d.i = 0; }
87     Date(const Date&) = delete;
88     Date& operator=(const Date&) = delete;
operator =Date89     Date& operator=(Date&& d) { i = d.i; d.i = 0; return *this;};
90 };
91 
operator ==(Oracle const & a,Oracle const & b)92 bool operator==( Oracle const& a, Oracle const& b ) { return a.val.i == b.val.i; }
operator !=(Oracle const & a,Oracle const & b)93 bool operator!=( Oracle const& a, Oracle const& b ) { return a.val.i != b.val.i; }
94 
95 
96 namespace tr2 = std::experimental;
97 
98 
TEST(disengaged_ctor)99 TEST(disengaged_ctor)
100 {
101     tr2::optional<int> o1;
102     assert (!o1);
103 
104     tr2::optional<int> o2 = tr2::nullopt;
105     assert (!o2);
106 
107     tr2::optional<int> o3 = o2;
108     assert (!o3);
109 
110     assert (o1 == tr2::nullopt);
111     assert (o1 == tr2::optional<int>{});
112     assert (!o1);
113     assert (bool(o1) == false);
114 
115     assert (o2 == tr2::nullopt);
116     assert (o2 == tr2::optional<int>{});
117     assert (!o2);
118     assert (bool(o2) == false);
119 
120     assert (o3 == tr2::nullopt);
121     assert (o3 == tr2::optional<int>{});
122     assert (!o3);
123     assert (bool(o3) == false);
124 
125     assert (o1 == o2);
126     assert (o2 == o1);
127     assert (o1 == o3);
128     assert (o3 == o1);
129     assert (o2 == o3);
130     assert (o3 == o2);
131 };
132 
133 
TEST(value_ctor)134 TEST(value_ctor)
135 {
136   OracleVal v;
137   tr2::optional<Oracle> oo1(v);
138   assert (oo1 != tr2::nullopt);
139   assert (oo1 != tr2::optional<Oracle>{});
140   assert (oo1 == tr2::optional<Oracle>{v});
141   assert (!!oo1);
142   assert (bool(oo1));
143   // NA: assert (oo1->s == sValueCopyConstructed);
144   assert (oo1->s == sMoveConstructed);
145   assert (v.s == sValueConstructed);
146 
147   tr2::optional<Oracle> oo2(std::move(v));
148   assert (oo2 != tr2::nullopt);
149   assert (oo2 != tr2::optional<Oracle>{});
150   assert (oo2 == oo1);
151   assert (!!oo2);
152   assert (bool(oo2));
153   // NA: assert (oo2->s == sValueMoveConstructed);
154   assert (oo2->s == sMoveConstructed);
155   assert (v.s == sMovedFrom);
156 
157   {
158       OracleVal v;
159       tr2::optional<Oracle> oo1{tr2::in_place, v};
160       assert (oo1 != tr2::nullopt);
161       assert (oo1 != tr2::optional<Oracle>{});
162       assert (oo1 == tr2::optional<Oracle>{v});
163       assert (!!oo1);
164       assert (bool(oo1));
165       assert (oo1->s == sValueCopyConstructed);
166       assert (v.s == sValueConstructed);
167 
168       tr2::optional<Oracle> oo2{tr2::in_place, std::move(v)};
169       assert (oo2 != tr2::nullopt);
170       assert (oo2 != tr2::optional<Oracle>{});
171       assert (oo2 == oo1);
172       assert (!!oo2);
173       assert (bool(oo2));
174       assert (oo2->s == sValueMoveConstructed);
175       assert (v.s == sMovedFrom);
176   }
177 };
178 
179 
TEST(assignment)180 TEST(assignment)
181 {
182     tr2::optional<int> oi;
183     oi = tr2::optional<int>{1};
184     assert (*oi == 1);
185 
186     oi = tr2::nullopt;
187     assert (!oi);
188 
189     oi = 2;
190     assert (*oi == 2);
191 
192     oi = {};
193     assert (!oi);
194 };
195 
196 
197 template <class T>
198 struct MoveAware
199 {
200   T val;
201   bool moved;
MoveAwareMoveAware202   MoveAware(T val) : val(val), moved(false) {}
203   MoveAware(MoveAware const&) = delete;
MoveAwareMoveAware204   MoveAware(MoveAware&& rhs) : val(rhs.val), moved(rhs.moved) {
205     rhs.moved = true;
206   }
207   MoveAware& operator=(MoveAware const&) = delete;
operator =MoveAware208   MoveAware& operator=(MoveAware&& rhs) {
209     val = (rhs.val);
210     moved = (rhs.moved);
211     rhs.moved = true;
212     return *this;
213   }
214 };
215 
TEST(moved_from_state)216 TEST(moved_from_state)
217 {
218   // first, test mock:
219   MoveAware<int> i{1}, j{2};
220   assert (i.val == 1);
221   assert (!i.moved);
222   assert (j.val == 2);
223   assert (!j.moved);
224 
225   MoveAware<int> k = std::move(i);
226   assert (k.val == 1);
227   assert (!k.moved);
228   assert (i.val == 1);
229   assert (i.moved);
230 
231   k = std::move(j);
232   assert (k.val == 2);
233   assert (!k.moved);
234   assert (j.val == 2);
235   assert (j.moved);
236 
237   // now, test optional
238   tr2::optional<MoveAware<int>> oi{1}, oj{2};
239   assert (oi);
240   assert (!oi->moved);
241   assert (oj);
242   assert (!oj->moved);
243 
244   tr2::optional<MoveAware<int>> ok = std::move(oi);
245   assert (ok);
246   assert (!ok->moved);
247   assert (oi);
248   assert (oi->moved);
249 
250   ok = std::move(oj);
251   assert (ok);
252   assert (!ok->moved);
253   assert (oj);
254   assert (oj->moved);
255 };
256 
257 
TEST(copy_move_ctor_optional_int)258 TEST(copy_move_ctor_optional_int)
259 {
260   tr2::optional<int> oi;
261   tr2::optional<int> oj = oi;
262 
263   assert (!oj);
264   assert (oj == oi);
265   assert (oj == tr2::nullopt);
266   assert (!bool(oj));
267 
268   oi = 1;
269   tr2::optional<int> ok = oi;
270   assert (!!ok);
271   assert (bool(ok));
272   assert (ok == oi);
273   assert (ok != oj);
274   assert (*ok == 1);
275 
276   tr2::optional<int> ol = std::move(oi);
277   assert (!!ol);
278   assert (bool(ol));
279   assert (ol == oi);
280   assert (ol != oj);
281   assert (*ol == 1);
282 };
283 
284 
TEST(optional_optional)285 TEST(optional_optional)
286 {
287   tr2::optional<tr2::optional<int>> oi1 = tr2::nullopt;
288   assert (oi1 == tr2::nullopt);
289   assert (!oi1);
290 
291   {
292   tr2::optional<tr2::optional<int>> oi2 {tr2::in_place};
293   assert (oi2 != tr2::nullopt);
294   assert (bool(oi2));
295   assert (*oi2 == tr2::nullopt);
296   //assert (!(*oi2));
297   //std::cout << typeid(**oi2).name() << std::endl;
298   }
299 
300   {
301   tr2::optional<tr2::optional<int>> oi2 {tr2::in_place, tr2::nullopt};
302   assert (oi2 != tr2::nullopt);
303   assert (bool(oi2));
304   assert (*oi2 == tr2::nullopt);
305   assert (!*oi2);
306   }
307 
308   {
309   tr2::optional<tr2::optional<int>> oi2 {tr2::optional<int>{}};
310   assert (oi2 != tr2::nullopt);
311   assert (bool(oi2));
312   assert (*oi2 == tr2::nullopt);
313   assert (!*oi2);
314   }
315 
316   tr2::optional<int> oi;
317   auto ooi = tr2::make_optional(oi);
318   static_assert( std::is_same<tr2::optional<tr2::optional<int>>, decltype(ooi)>::value, "");
319 
320 };
321 
TEST(example_guard)322 TEST(example_guard)
323 {
324   using namespace tr2;
325   //FAILS: optional<Guard> ogx(Guard("res1"));
326   //FAILS: optional<Guard> ogx = "res1";
327   //FAILS: optional<Guard> ogx("res1");
328   optional<Guard> oga;                     // Guard is non-copyable (and non-moveable)
329   optional<Guard> ogb(in_place, "res1");   // initialzes the contained value with "res1"
330   assert (bool(ogb));
331   assert (ogb->val == "res1");
332 
333   optional<Guard> ogc(in_place);           // default-constructs the contained value
334   assert (bool(ogc));
335   assert (ogc->val == "");
336 
337   oga.emplace("res1");                     // initialzes the contained value with "res1"
338   assert (bool(oga));
339   assert (oga->val == "res1");
340 
341   oga.emplace();                           // destroys the contained value and
342                                            // default-constructs the new one
343   assert (bool(oga));
344   assert (oga->val == "");
345 
346   oga = nullopt;                        // OK: make disengaged the optional Guard
347   assert (!(oga));
348   //FAILS: ogb = {};                          // ERROR: Guard is not Moveable
349 };
350 
351 
process()352 void process(){}
process(int)353 void process(int ){}
processNil()354 void processNil(){}
355 
356 
TEST(example1)357 TEST(example1)
358 {
359   using namespace tr2;
360   optional<int> oi;                 // create disengaged object
361   optional<int> oj = nullopt;          // alternative syntax
362   oi = oj;                          // assign disengaged object
363   optional<int> ok = oj;            // ok is disengaged
364 
365   if (oi)  assert(false);           // 'if oi is engaged...'
366   if (!oi) assert(true);            // 'if oi is disengaged...'
367 
368   if (oi != nullopt) assert(false);    // 'if oi is engaged...'
369   if (oi == nullopt) assert(true);     // 'if oi is disengaged...'
370 
371   assert(oi == ok);                 // two disengaged optionals compare equal
372 
373   ///////////////////////////////////////////////////////////////////////////
374   optional<int> ol{1};              // ol is engaged; its contained value is 1
375   ok = 2;                           // ok becomes engaged; its contained value is 2
376   oj = ol;                          // oj becomes engaged; its contained value is 1
377 
378   assert(oi != ol);                 // disengaged != engaged
379   assert(ok != ol);                 // different contained values
380   assert(oj == ol);                 // same contained value
381   assert(oi < ol);                  // disengaged < engaged
382   assert(ol < ok);                  // less by contained value
383 
384   /////////////////////////////////////////////////////////////////////////////
385   optional<int> om{1};              // om is engaged; its contained value is 1
386   optional<int> on = om;            // on is engaged; its contained value is 1
387   om = 2;                           // om is engaged; its contained value is 2
388   assert (on != om);                // on still contains 3. They are not pointers
389 
390   /////////////////////////////////////////////////////////////////////////////
391   int i = *ol;                      // i obtains the value contained in ol
392   assert (i == 1);
393   *ol = 9;                          // the object contained in ol becomes 9
394   assert(*ol == 9);
395   assert(ol == make_optional(9));
396 
397   ///////////////////////////////////
398   int p = 1;
399   optional<int> op = p;
400   assert(*op == 1);
401   p = 2;
402   assert(*op == 1);                 // value contained in op is separated from p
403 
404   ////////////////////////////////
405   if (ol)
406     process(*ol);                   // use contained value if present
407   else
408     process();                      // proceed without contained value
409 
410   if (!om)
411     processNil();
412   else
413     process(*om);
414 
415   /////////////////////////////////////////
416   process(ol.value_or(0));     // use 0 if ol is disengaged
417 
418   ////////////////////////////////////////////
419   ok = nullopt;                         // if ok was engaged calls T's dtor
420   oj = {};                           // assigns a temporary disengaged optional
421 };
422 
423 
TEST(example_guard)424 TEST(example_guard)
425 {
426   using std::experimental::optional;
427   const optional<int> c = 4;
428   int i = *c;                        // i becomes 4
429   assert (i == 4);
430   // FAILS: *c = i;                            // ERROR: cannot assign to const int&
431 };
432 
433 
TEST(example_ref)434 TEST(example_ref)
435 {
436   using namespace std::experimental;
437   int i = 1;
438   int j = 2;
439   optional<int&> ora;                 // disengaged optional reference to int
440   optional<int&> orb = i;             // contained reference refers to object i
441 
442   *orb = 3;                          // i becomes 3
443   // FAILS: ora = j;                           // ERROR: optional refs do not have assignment from T
444   // FAILS: ora = {j};                         // ERROR: optional refs do not have copy/move assignment
445   // FAILS: ora = orb;                         // ERROR: no copy/move assignment
446   ora.emplace(j);                    // OK: contained reference refers to object j
447   ora.emplace(i);                    // OK: contained reference now refers to object i
448 
449   ora = nullopt;                        // OK: ora becomes disengaged
450 };
451 
452 
453 template <typename T>
getValue(tr2::optional<T> newVal=tr2::nullopt,tr2::optional<T &> storeHere=tr2::nullopt)454 T getValue( tr2::optional<T> newVal = tr2::nullopt, tr2::optional<T&> storeHere = tr2::nullopt )
455 {
456   T cached{};
457 
458   if (newVal) {
459     cached = *newVal;
460 
461     if (storeHere) {
462       *storeHere = *newVal; // LEGAL: assigning T to T
463     }
464   }
465   return cached;
466 }
467 
TEST(example_optional_arg)468 TEST(example_optional_arg)
469 {
470   int iii = 0;
471   iii = getValue<int>(iii, iii);
472   iii = getValue<int>(iii);
473   iii = getValue<int>();
474 
475   {
476     using namespace std::experimental;
477     optional<Guard> grd1{in_place, "res1", 1};   // guard 1 initialized
478     optional<Guard> grd2;
479 
480     grd2.emplace("res2", 2);                     // guard 2 initialized
481     grd1 = nullopt;                                 // guard 1 released
482 
483   }                                              // guard 2 released (in dtor)
484 };
485 
486 
getStartMidEnd()487 std::tuple<Date, Date, Date> getStartMidEnd() { return std::tuple<Date, Date, Date>{Date{1}, Date{2}, Date{3}}; }
run(Date const &,Date const &,Date const &)488 void run(Date const&, Date const&, Date const&) {}
489 
TEST(example_date)490 TEST(example_date)
491 {
492   using namespace std::experimental;
493   optional<Date> start, mid, end;           // Date doesn't have default ctor (no good default date)
494 
495   std::tie(start, mid, end) = getStartMidEnd();
496   run(*start, *mid, *end);
497 };
498 
499 
readNextChar()500 std::experimental::optional<char> readNextChar(){ return{}; }
501 
run(std::experimental::optional<std::string>)502 void run(std::experimental::optional<std::string>) {}
run(std::complex<double>)503 void run(std::complex<double>) {}
504 
505 
506 template <class T>
assign_norebind(tr2::optional<T &> & optref,T & obj)507 void assign_norebind(tr2::optional<T&>& optref, T& obj)
508 {
509   if (optref) *optref = obj;
510   else        optref.emplace(obj);
511 }
512 
unused(T &&)513 template <typename T> void unused(T&&) {}
514 
TEST(example_conceptual_model)515 TEST(example_conceptual_model)
516 {
517   using namespace std::experimental;
518 
519   optional<int> oi = 0;
520   optional<int> oj = 1;
521   optional<int> ok = nullopt;
522 
523   oi = 1;
524   oj = nullopt;
525   ok = 0;
526 
527   unused(oi == nullopt);
528   unused(oj == 0);
529   unused(ok == 1);
530 };
531 
TEST(example_rationale)532 TEST(example_rationale)
533 {
534   using namespace std::experimental;
535   if (optional<char> ch = readNextChar()) {
536     unused(ch);
537     // ...
538   }
539 
540   //////////////////////////////////
541   optional<int> opt1 = nullopt;
542   optional<int> opt2 = {};
543 
544   opt1 = nullopt;
545   opt2 = {};
546 
547   if (opt1 == nullopt) {}
548   if (!opt2) {}
549   if (opt2 == optional<int>{}) {}
550 
551 
552 
553   ////////////////////////////////
554 
555   run(nullopt);            // pick the second overload
556   // FAILS: run({});              // ambiguous
557 
558   if (opt1 == nullopt) {} // fine
559   // FAILS: if (opt2 == {}) {}   // illegal
560 
561   ////////////////////////////////
562   assert (optional<unsigned>{}  < optional<unsigned>{0});
563   assert (optional<unsigned>{0} < optional<unsigned>{1});
564   assert (!(optional<unsigned>{}  < optional<unsigned>{}) );
565   assert (!(optional<unsigned>{1} < optional<unsigned>{1}));
566 
567   assert (optional<unsigned>{}  != optional<unsigned>{0});
568   assert (optional<unsigned>{0} != optional<unsigned>{1});
569   assert (optional<unsigned>{}  == optional<unsigned>{} );
570   assert (optional<unsigned>{0} == optional<unsigned>{0});
571 
572   /////////////////////////////////
573   optional<int> o;
574   o = make_optional(1);         // copy/move assignment
575   o = 1;           // assignment from T
576   o.emplace(1);    // emplacement
577 
578   ////////////////////////////////////
579   int isas = 0, i = 9;
580   optional<int&> asas = i;
581   assign_norebind(asas, isas);
582 
583   /////////////////////////////////////
584   ////tr2::optional<std::vector<int>> ov2 = {2, 3};
585   ////assert (bool(ov2));
586   ////assert ((*ov2)[1] == 3);
587   ////
588   ////////////////////////////////
589   ////std::vector<int> v = {1, 2, 4, 8};
590   ////optional<std::vector<int>> ov = {1, 2, 4, 8};
591 
592   ////assert (v == *ov);
593   ////
594   ////ov = {1, 2, 4, 8};
595 
596   ////std::allocator<int> a;
597   ////optional<std::vector<int>> ou { in_place, {1, 2, 4, 8}, a };
598 
599   ////assert (ou == ov);
600 
601   //////////////////////////////
602   // inconvenient syntax:
603   {
604 
605       tr2::optional<std::vector<int>> ov2{tr2::in_place, {2, 3}};
606 
607       assert (bool(ov2));
608       assert ((*ov2)[1] == 3);
609 
610       ////////////////////////////
611 
612       std::vector<int> v = {1, 2, 4, 8};
613       optional<std::vector<int>> ov{tr2::in_place, {1, 2, 4, 8}};
614 
615       assert (v == *ov);
616 
617       ov.emplace({1, 2, 4, 8});
618 /*
619       std::allocator<int> a;
620       optional<std::vector<int>> ou { in_place, {1, 2, 4, 8}, a };
621 
622       assert (ou == ov);
623 */
624   }
625 
626   /////////////////////////////////
627   {
628   typedef int T;
629   optional<optional<T>> ot {in_place};
630   optional<optional<T>> ou {in_place, nullopt};
631   optional<optional<T>> ov {optional<T>{}};
632 
633   optional<int> oi;
634   auto ooi = make_optional(oi);
635   static_assert( std::is_same<optional<optional<int>>, decltype(ooi)>::value, "");
636   }
637 };
638 
639 
fun(std::string,std::experimental::optional<int> oi=std::experimental::nullopt)640 bool fun(std::string , std::experimental::optional<int> oi = std::experimental::nullopt)
641 {
642   return bool(oi);
643 }
644 
TEST(example_converting_ctor)645 TEST(example_converting_ctor)
646 {
647   using namespace std::experimental;
648 
649   assert (true == fun("dog", 2));
650   assert (false == fun("dog"));
651   assert (false == fun("dog", nullopt)); // just to be explicit
652 };
653 
654 
TEST(bad_comparison)655 TEST(bad_comparison)
656 {
657   tr2::optional<int> oi, oj;
658   int i;
659   bool b = (oi == oj);
660   b = (oi >= i);
661   b = (oi == i);
662   unused(b);
663 };
664 
665 
666 //// NOT APPLICABLE ANYMORE
667 ////TEST(perfect_ctor)
668 ////{
669 ////  //tr2::optional<std::string> ois = "OS";
670 ////  assert (*ois == "OS");
671 ////
672 ////  // FAILS: tr2::optional<ExplicitStr> oes = "OS";
673 ////  tr2::optional<ExplicitStr> oes{"OS"};
674 ////  assert (oes->s == "OS");
675 ////};
676 
TEST(value_or)677 TEST(value_or)
678 {
679   tr2::optional<int> oi = 1;
680   int i = oi.value_or(0);
681   assert (i == 1);
682 
683   oi = tr2::nullopt;
684   assert (oi.value_or(3) == 3);
685 
686   tr2::optional<std::string> os{"AAA"};
687   assert (os.value_or("BBB") == "AAA");
688   os = {};
689   assert (os.value_or("BBB") == "BBB");
690 };
691 
TEST(mixed_order)692 TEST(mixed_order)
693 {
694   using namespace std::experimental;
695 
696   optional<int> oN {nullopt};
697   optional<int> o0 {0};
698   optional<int> o1 {1};
699 
700   assert ( (oN <   0));
701   assert ( (oN <   1));
702   assert (!(o0 <   0));
703   assert ( (o0 <   1));
704   assert (!(o1 <   0));
705   assert (!(o1 <   1));
706 
707   assert (!(oN >=  0));
708   assert (!(oN >=  1));
709   assert ( (o0 >=  0));
710   assert (!(o0 >=  1));
711   assert ( (o1 >=  0));
712   assert ( (o1 >=  1));
713 
714   assert (!(oN >   0));
715   assert (!(oN >   1));
716   assert (!(o0 >   0));
717   assert (!(o0 >   1));
718   assert ( (o1 >   0));
719   assert (!(o1 >   1));
720 
721   assert ( (oN <=  0));
722   assert ( (oN <=  1));
723   assert ( (o0 <=  0));
724   assert ( (o0 <=  1));
725   assert (!(o1 <=  0));
726   assert ( (o1 <=  1));
727 
728   assert ( (0 >  oN));
729   assert ( (1 >  oN));
730   assert (!(0 >  o0));
731   assert ( (1 >  o0));
732   assert (!(0 >  o1));
733   assert (!(1 >  o1));
734 
735   assert (!(0 <= oN));
736   assert (!(1 <= oN));
737   assert ( (0 <= o0));
738   assert (!(1 <= o0));
739   assert ( (0 <= o1));
740   assert ( (1 <= o1));
741 
742   assert (!(0 <  oN));
743   assert (!(1 <  oN));
744   assert (!(0 <  o0));
745   assert (!(1 <  o0));
746   assert ( (0 <  o1));
747   assert (!(1 <  o1));
748 
749   assert ( (0 >= oN));
750   assert ( (1 >= oN));
751   assert ( (0 >= o0));
752   assert ( (1 >= o0));
753   assert (!(0 >= o1));
754   assert ( (1 >= o1));
755 };
756 
757 struct BadRelops
758 {
759   int i;
760 };
761 
operator <(BadRelops a,BadRelops b)762 constexpr bool operator<(BadRelops a, BadRelops b) { return a.i < b.i; }
operator >(BadRelops a,BadRelops b)763 constexpr bool operator>(BadRelops a, BadRelops b) { return a.i < b.i; } // intentional error!
764 
TEST(bad_relops)765 TEST(bad_relops)
766 {
767   using namespace std::experimental;
768   BadRelops a{1}, b{2};
769   assert (a < b);
770   assert (a > b);
771 
772   optional<BadRelops> oa = a, ob = b;
773   assert (oa < ob);
774   assert (!(oa > ob));
775 
776   assert (oa < b);
777   assert (oa > b);
778 
779   optional<BadRelops&> ra = a, rb = b;
780   assert (ra < rb);
781   assert (!(ra > rb));
782 
783   assert (ra < b);
784   assert (ra > b);
785 };
786 
787 
TEST(mixed_equality)788 TEST(mixed_equality)
789 {
790   using namespace std::experimental;
791 
792   assert (make_optional(0) == 0);
793   assert (make_optional(1) == 1);
794   assert (make_optional(0) != 1);
795   assert (make_optional(1) != 0);
796 
797   optional<int> oN {nullopt};
798   optional<int> o0 {0};
799   optional<int> o1 {1};
800 
801   assert (o0 ==  0);
802   assert ( 0 == o0);
803   assert (o1 ==  1);
804   assert ( 1 == o1);
805   assert (o1 !=  0);
806   assert ( 0 != o1);
807   assert (o0 !=  1);
808   assert ( 1 != o0);
809 
810   assert ( 1 != oN);
811   assert ( 0 != oN);
812   assert (oN !=  1);
813   assert (oN !=  0);
814   assert (!( 1 == oN));
815   assert (!( 0 == oN));
816   assert (!(oN ==  1));
817   assert (!(oN ==  0));
818 
819   std::string cat{"cat"}, dog{"dog"};
820   optional<std::string> oNil{}, oDog{"dog"}, oCat{"cat"};
821 
822   assert (oCat ==  cat);
823   assert ( cat == oCat);
824   assert (oDog ==  dog);
825   assert ( dog == oDog);
826   assert (oDog !=  cat);
827   assert ( cat != oDog);
828   assert (oCat !=  dog);
829   assert ( dog != oCat);
830 
831   assert ( dog != oNil);
832   assert ( cat != oNil);
833   assert (oNil !=  dog);
834   assert (oNil !=  cat);
835   assert (!( dog == oNil));
836   assert (!( cat == oNil));
837   assert (!(oNil ==  dog));
838   assert (!(oNil ==  cat));
839 };
840 
TEST(const_propagation)841 TEST(const_propagation)
842 {
843   using namespace std::experimental;
844 
845   optional<int> mmi{0};
846   static_assert(std::is_same<decltype(*mmi), int&>::value, "WTF");
847 
848   const optional<int> cmi{0};
849   static_assert(std::is_same<decltype(*cmi), const int&>::value, "WTF");
850 
851   optional<const int> mci{0};
852   static_assert(std::is_same<decltype(*mci), const int&>::value, "WTF");
853 
854   optional<const int> cci{0};
855   static_assert(std::is_same<decltype(*cci), const int&>::value, "WTF");
856 };
857 
858 
859 static_assert(std::is_base_of<std::logic_error, std::experimental::bad_optional_access>::value, "");
860 
TEST(safe_value)861 TEST(safe_value)
862 {
863   using namespace std::experimental;
864 
865   try {
866     optional<int> ovN{}, ov1{1};
867 
868     int& r1 = ov1.value();
869     assert (r1 == 1);
870 
871     try {
872       ovN.value();
873       assert (false);
874     }
875     catch (bad_optional_access const&) {
876     }
877 
878     { // ref variant
879       int i1 = 1;
880       optional<int&> orN{}, or1{i1};
881 
882       int& r2 = or1.value();
883       assert (r2 == 1);
884 
885       try {
886         orN.value();
887         assert (false);
888       }
889       catch (bad_optional_access const&) {
890       }
891     }
892   }
893   catch(...) {
894     assert (false);
895   }
896 };
897 
TEST(optional_ref)898 TEST(optional_ref)
899 {
900   using namespace tr2;
901   // FAILS: optional<int&&> orr;
902   // FAILS: optional<nullopt_t&> on;
903   int i = 8;
904   optional<int&> ori;
905   assert (!ori);
906   ori.emplace(i);
907   assert (bool(ori));
908   assert (*ori == 8);
909   assert (&*ori == &i);
910   *ori = 9;
911   assert (i == 9);
912 
913   // FAILS: int& ir = ori.value_or(i);
914   int ii = ori.value_or(i);
915   assert (ii == 9);
916   ii = 7;
917   assert (*ori == 9);
918 
919   int j = 22;
920   auto&& oj = make_optional(std::ref(j));
921   *oj = 23;
922   assert (&*oj == &j);
923   assert (j == 23);
924 };
925 
TEST(optional_ref_const_propagation)926 TEST(optional_ref_const_propagation)
927 {
928   using namespace std::experimental;
929 
930   int i = 9;
931   const optional<int&> mi = i;
932   int& r = *mi;
933   optional<const int&> ci = i;
934   static_assert(std::is_same<decltype(*mi), int&>::value, "WTF");
935   static_assert(std::is_same<decltype(*ci), const int&>::value, "WTF");
936 
937   unused(r);
938 };
939 
TEST(optional_ref_assign)940 TEST(optional_ref_assign)
941 {
942   using namespace std::experimental;
943 
944   int i = 9;
945   optional<int&> ori = i;
946 
947   int j = 1;
948   ori = optional<int&>{j};
949   ori = {j};
950   // FAILS: ori = j;
951 
952   optional<int&> orx = ori;
953   ori = orx;
954 
955   optional<int&> orj = j;
956 
957   assert (ori);
958   assert (*ori == 1);
959   assert (ori == orj);
960   assert (i == 9);
961 
962   *ori = 2;
963   assert (*ori == 2);
964   assert (ori == 2);
965   assert (2 == ori);
966   assert (ori != 3);
967 
968   assert (ori == orj);
969   assert (j == 2);
970   assert (i == 9);
971 
972   ori = {};
973   assert (!ori);
974   assert (ori != orj);
975   assert (j == 2);
976   assert (i == 9);
977 };
978 
979 
TEST(optional_ref_swap)980 TEST(optional_ref_swap)
981 {
982   using namespace std::experimental;
983   int i = 0;
984   int j = 1;
985   optional<int&> oi = i;
986   optional<int&> oj = j;
987 
988   assert (&*oi == &i);
989   assert (&*oj == &j);
990 
991   swap(oi, oj);
992   assert (&*oi == &j);
993   assert (&*oj == &i);
994 };
995 
TEST(optional_initialization)996 TEST(optional_initialization)
997 {
998     using namespace tr2;
999     using std::string;
1000     string s = "STR";
1001 
1002     optional<string> os{s};
1003     optional<string> ot = s;
1004     optional<string> ou{"STR"};
1005     optional<string> ov = string{"STR"};
1006 
1007 };
1008 
1009 #include <unordered_set>
1010 
TEST(optional_hashing)1011 TEST(optional_hashing)
1012 {
1013     using namespace tr2;
1014     using std::string;
1015 
1016     std::hash<int> hi;
1017     std::hash<optional<int>> hoi;
1018     std::hash<string> hs;
1019     std::hash<optional<string>> hos;
1020 
1021     assert (hi(0) == hoi(optional<int>{0}));
1022     assert (hi(1) == hoi(optional<int>{1}));
1023     assert (hi(3198) == hoi(optional<int>{3198}));
1024 
1025     assert (hs("") == hos(optional<string>{""}));
1026     assert (hs("0") == hos(optional<string>{"0"}));
1027     assert (hs("Qa1#") == hos(optional<string>{"Qa1#"}));
1028 
1029     std::unordered_set<optional<string>> set;
1030     assert(set.find({"Qa1#"}) == set.end());
1031 
1032     set.insert({"0"});
1033     assert(set.find({"Qa1#"}) == set.end());
1034 
1035     set.insert({"Qa1#"});
1036     assert(set.find({"Qa1#"}) != set.end());
1037 };
1038 
1039 
1040 // optional_ref_emulation
1041 template <class T>
1042 struct generic
1043 {
1044   typedef T type;
1045 };
1046 
1047 template <class U>
1048 struct generic<U&>
1049 {
1050   typedef std::reference_wrapper<U> type;
1051 };
1052 
1053 template <class T>
1054 using Generic = typename generic<T>::type;
1055 
1056 template <class X>
generic_fun()1057 bool generic_fun()
1058 {
1059   std::experimental::optional<Generic<X>> op;
1060   return bool(op);
1061 }
1062 
TEST(optional_ref_emulation)1063 TEST(optional_ref_emulation)
1064 {
1065   using namespace std::experimental;
1066   optional<Generic<int>> oi = 1;
1067   assert (*oi == 1);
1068 
1069   int i = 8;
1070   int j = 4;
1071   optional<Generic<int&>> ori {i};
1072   assert (*ori == 8);
1073   assert ((void*)&*ori != (void*)&i); // !DIFFERENT THAN optional<T&>
1074 
1075   *ori = j;
1076   assert (*ori == 4);
1077 };
1078 
1079 
1080 # if OPTIONAL_HAS_THIS_RVALUE_REFS == 1
TEST(moved_on_value_or)1081 TEST(moved_on_value_or)
1082 {
1083   using namespace tr2;
1084   optional<Oracle> oo{in_place};
1085 
1086   assert (oo);
1087   assert (oo->s == sDefaultConstructed);
1088 
1089   Oracle o = std::move(oo).value_or( Oracle{OracleVal{}} );
1090   assert (oo);
1091   assert (oo->s == sMovedFrom);
1092   assert (o.s == sMoveConstructed);
1093 
1094   optional<MoveAware<int>> om {in_place, 1};
1095   assert (om);
1096   assert (om->moved == false);
1097 
1098   /*MoveAware<int> m =*/ std::move(om).value_or( MoveAware<int>{1} );
1099   assert (om);
1100   assert (om->moved == true);
1101 
1102 # if OPTIONAL_HAS_MOVE_ACCESSORS == 1
1103   {
1104     Date d = optional<Date>{in_place, 1}.value();
1105     assert (d.i); // to silence compiler warning
1106 
1107 	Date d2 = *optional<Date>{in_place, 1};
1108     assert (d2.i); // to silence compiler warning
1109   }
1110 # endif
1111 };
1112 # endif
1113 
1114 
TEST(optional_ref_hashing)1115 TEST(optional_ref_hashing)
1116 {
1117     using namespace tr2;
1118     using std::string;
1119 
1120     std::hash<int> hi;
1121     std::hash<optional<int&>> hoi;
1122     std::hash<string> hs;
1123     std::hash<optional<string&>> hos;
1124 
1125     int i0 = 0;
1126     int i1 = 1;
1127     assert (hi(0) == hoi(optional<int&>{i0}));
1128     assert (hi(1) == hoi(optional<int&>{i1}));
1129 
1130     string s{""};
1131     string s0{"0"};
1132     string sCAT{"CAT"};
1133     assert (hs("") == hos(optional<string&>{s}));
1134     assert (hs("0") == hos(optional<string&>{s0}));
1135     assert (hs("CAT") == hos(optional<string&>{sCAT}));
1136 
1137     std::unordered_set<optional<string&>> set;
1138     assert(set.find({sCAT}) == set.end());
1139 
1140     set.insert({s0});
1141     assert(set.find({sCAT}) == set.end());
1142 
1143     set.insert({sCAT});
1144     assert(set.find({sCAT}) != set.end());
1145 };
1146 
1147 struct Combined
1148 {
1149   int m = 0;
1150   int n = 1;
1151 
CombinedCombined1152   constexpr Combined() : m{5}, n{6} {}
CombinedCombined1153   constexpr Combined(int m, int n) : m{m}, n{n} {}
1154 };
1155 
1156 struct Nasty
1157 {
1158   int m = 0;
1159   int n = 1;
1160 
NastyNasty1161   constexpr Nasty() : m{5}, n{6} {}
NastyNasty1162   constexpr Nasty(int m, int n) : m{m}, n{n} {}
1163 
operator &Nasty1164   int operator&() { return n; }
operator &Nasty1165   int operator&() const { return n; }
1166 };
1167 
TEST(arrow_operator)1168 TEST(arrow_operator)
1169 {
1170   using namespace std::experimental;
1171 
1172   optional<Combined> oc1{in_place, 1, 2};
1173   assert (oc1);
1174   assert (oc1->m == 1);
1175   assert (oc1->n == 2);
1176 
1177   optional<Nasty> on{in_place, 1, 2};
1178   assert (on);
1179   assert (on->m == 1);
1180   assert (on->n == 2);
1181 };
1182 
TEST(arrow_wit_optional_ref)1183 TEST(arrow_wit_optional_ref)
1184 {
1185   using namespace std::experimental;
1186 
1187   Combined c{1, 2};
1188   optional<Combined&> oc = c;
1189   assert (oc);
1190   assert (oc->m == 1);
1191   assert (oc->n == 2);
1192 
1193   Nasty n{1, 2};
1194   Nasty m{3, 4};
1195   Nasty p{5, 6};
1196 
1197   optional<Nasty&> on{n};
1198   assert (on);
1199   assert (on->m == 1);
1200   assert (on->n == 2);
1201 
1202   on = {m};
1203   assert (on);
1204   assert (on->m == 3);
1205   assert (on->n == 4);
1206 
1207   on.emplace(p);
1208   assert (on);
1209   assert (on->m == 5);
1210   assert (on->n == 6);
1211 
1212   optional<Nasty&> om{in_place, n};
1213   assert (om);
1214   assert (om->m == 1);
1215   assert (om->n == 2);
1216 };
1217 
TEST(no_dangling_reference_in_value)1218 TEST(no_dangling_reference_in_value)
1219 {
1220   // this mostly tests compiler warnings
1221   using namespace std::experimental;
1222   optional<int> oi {2};
1223   unused (oi.value());
1224   const optional<int> coi {3};
1225   unused (coi.value());
1226 };
1227 
1228 struct CountedObject
1229 {
1230   static int _counter;
1231   bool _throw;
CountedObjectCountedObject1232   CountedObject(bool b) : _throw(b) { ++_counter; }
CountedObjectCountedObject1233   CountedObject(CountedObject const& rhs) : _throw(rhs._throw) { if (_throw) throw int(); }
~CountedObjectCountedObject1234   ~CountedObject() { --_counter; }
1235 };
1236 
1237 int CountedObject::_counter = 0;
1238 
TEST(exception_safety)1239 TEST(exception_safety)
1240 {
1241   using namespace std::experimental;
1242   try {
1243     optional<CountedObject> oo(in_place, true); // throw
1244     optional<CountedObject> o1(oo);
1245   }
1246   catch(...)
1247   {
1248     //
1249   }
1250   assert(CountedObject::_counter == 0);
1251 
1252   try {
1253     optional<CountedObject> oo(in_place, true); // throw
1254     optional<CountedObject> o1(std::move(oo));  // now move
1255   }
1256   catch(...)
1257   {
1258     //
1259   }
1260   assert(CountedObject::_counter == 0);
1261 };
1262 
1263 //// constexpr tests
1264 
1265 // these 4 classes have different noexcept signatures in move operations
1266 struct NothrowBoth {
NothrowBothNothrowBoth1267   NothrowBoth(NothrowBoth&&) noexcept(true) {};
operator =NothrowBoth1268   void operator=(NothrowBoth&&) noexcept(true) {};
1269 };
1270 struct NothrowCtor {
NothrowCtorNothrowCtor1271   NothrowCtor(NothrowCtor&&) noexcept(true) {};
operator =NothrowCtor1272   void operator=(NothrowCtor&&) noexcept(false) {};
1273 };
1274 struct NothrowAssign {
NothrowAssignNothrowAssign1275   NothrowAssign(NothrowAssign&&) noexcept(false) {};
operator =NothrowAssign1276   void operator=(NothrowAssign&&) noexcept(true) {};
1277 };
1278 struct NothrowNone {
NothrowNoneNothrowNone1279   NothrowNone(NothrowNone&&) noexcept(false) {};
operator =NothrowNone1280   void operator=(NothrowNone&&) noexcept(false) {};
1281 };
1282 
test_noexcept()1283 void test_noexcept()
1284 {
1285   {
1286     tr2::optional<NothrowBoth> b1, b2;
1287     static_assert(noexcept(tr2::optional<NothrowBoth>{tr2::constexpr_move(b1)}), "bad noexcept!");
1288     static_assert(noexcept(b1 = tr2::constexpr_move(b2)), "bad noexcept!");
1289   }
1290   {
1291     tr2::optional<NothrowCtor> c1, c2;
1292     static_assert(noexcept(tr2::optional<NothrowCtor>{tr2::constexpr_move(c1)}), "bad noexcept!");
1293     static_assert(!noexcept(c1 = tr2::constexpr_move(c2)), "bad noexcept!");
1294   }
1295   {
1296     tr2::optional<NothrowAssign> a1, a2;
1297     static_assert(!noexcept(tr2::optional<NothrowAssign>{tr2::constexpr_move(a1)}), "bad noexcept!");
1298     static_assert(!noexcept(a1 = tr2::constexpr_move(a2)), "bad noexcept!");
1299   }
1300   {
1301     tr2::optional<NothrowNone> n1, n2;
1302     static_assert(!noexcept(tr2::optional<NothrowNone>{tr2::constexpr_move(n1)}), "bad noexcept!");
1303     static_assert(!noexcept(n1 = tr2::constexpr_move(n2)), "bad noexcept!");
1304   }
1305 }
1306 
1307 
constexpr_test_disengaged()1308 void constexpr_test_disengaged()
1309 {
1310   constexpr tr2::optional<int> g0{};
1311   constexpr tr2::optional<int> g1{tr2::nullopt};
1312   static_assert( !g0, "initialized!" );
1313   static_assert( !g1, "initialized!" );
1314 
1315   static_assert( bool(g1) == bool(g0), "ne!" );
1316 
1317   static_assert( g1 == g0, "ne!" );
1318   static_assert( !(g1 != g0), "ne!" );
1319   static_assert( g1 >= g0, "ne!" );
1320   static_assert( !(g1 > g0), "ne!" );
1321   static_assert( g1 <= g0, "ne!" );
1322   static_assert( !(g1 <g0), "ne!" );
1323 
1324   static_assert( g1 == tr2::nullopt, "!" );
1325   static_assert( !(g1 != tr2::nullopt), "!" );
1326   static_assert( g1 <= tr2::nullopt, "!" );
1327   static_assert( !(g1 < tr2::nullopt), "!" );
1328   static_assert( g1 >= tr2::nullopt, "!" );
1329   static_assert( !(g1 > tr2::nullopt), "!" );
1330 
1331   static_assert(  (tr2::nullopt == g0), "!" );
1332   static_assert( !(tr2::nullopt != g0), "!" );
1333   static_assert(  (tr2::nullopt >= g0), "!" );
1334   static_assert( !(tr2::nullopt >  g0), "!" );
1335   static_assert(  (tr2::nullopt <= g0), "!" );
1336   static_assert( !(tr2::nullopt <  g0), "!" );
1337 
1338   static_assert(  (g1 != tr2::optional<int>(1)), "!" );
1339   static_assert( !(g1 == tr2::optional<int>(1)), "!" );
1340   static_assert(  (g1 <  tr2::optional<int>(1)), "!" );
1341   static_assert(  (g1 <= tr2::optional<int>(1)), "!" );
1342   static_assert( !(g1 >  tr2::optional<int>(1)), "!" );
1343   static_assert( !(g1 >  tr2::optional<int>(1)), "!" );
1344 }
1345 
1346 
1347 constexpr tr2::optional<int> g0{};
1348 constexpr tr2::optional<int> g2{2};
1349 static_assert( g2, "not initialized!" );
1350 static_assert( *g2 == 2, "not 2!" );
1351 static_assert( g2 == tr2::optional<int>(2), "not 2!" );
1352 static_assert( g2 != g0, "eq!" );
1353 
1354 # if OPTIONAL_HAS_MOVE_ACCESSORS == 1
1355 static_assert( *tr2::optional<int>{3} == 3, "WTF!" );
1356 static_assert( tr2::optional<int>{3}.value() == 3, "WTF!" );
1357 static_assert( tr2::optional<int>{3}.value_or(1) == 3, "WTF!" );
1358 static_assert( tr2::optional<int>{}.value_or(4) == 4, "WTF!" );
1359 # endif
1360 
1361 constexpr tr2::optional<Combined> gc0{tr2::in_place};
1362 static_assert(gc0->n == 6, "WTF!");
1363 
1364 // optional refs
1365 int gi = 0;
1366 constexpr tr2::optional<int&> gori = gi;
1367 constexpr tr2::optional<int&> gorn{};
1368 constexpr int& gri = *gori;
1369 static_assert(gori, "WTF");
1370 static_assert(!gorn, "WTF");
1371 static_assert(gori != tr2::nullopt, "WTF");
1372 static_assert(gorn == tr2::nullopt, "WTF");
1373 static_assert(&gri == &*gori, "WTF");
1374 
1375 constexpr int gci = 1;
1376 constexpr tr2::optional<int const&> gorci = gci;
1377 constexpr tr2::optional<int const&> gorcn{};
1378 
1379 static_assert(gorcn <  gorci, "WTF");
1380 static_assert(gorcn <= gorci, "WTF");
1381 static_assert(gorci == gorci, "WTF");
1382 static_assert(*gorci == 1, "WTF");
1383 static_assert(gorci == gci, "WTF");
1384 
1385 namespace constexpr_optional_ref_and_arrow
1386 {
1387   using namespace std::experimental;
1388   constexpr Combined c{1, 2};
1389   constexpr optional<Combined const&> oc = c;
1390   static_assert(oc, "WTF!");
1391   static_assert(oc->m == 1, "WTF!");
1392   static_assert(oc->n == 2, "WTF!");
1393 }
1394 
1395 #if OPTIONAL_HAS_CONSTEXPR_INIT_LIST
1396 
1397 namespace InitList
1398 {
1399   using namespace std::experimental;
1400 
1401   struct ConstInitLister
1402   {
1403     template <typename T>
ConstInitListerInitList::ConstInitLister1404 	constexpr ConstInitLister(std::initializer_list<T> il) : len (il.size()) {}
1405     size_t len;
1406   };
1407 
1408   constexpr ConstInitLister CIL {2, 3, 4};
1409   static_assert(CIL.len == 3, "WTF!");
1410 
1411   constexpr optional<ConstInitLister> oil {in_place, {4, 5, 6, 7}};
1412   static_assert(oil, "WTF!");
1413   static_assert(oil->len == 4, "WTF!");
1414 }
1415 
1416 #endif // OPTIONAL_HAS_CONSTEXPR_INIT_LIST
1417 
1418 // end constexpr tests
1419 
1420 
1421 #include <string>
1422 
1423 
1424 struct VEC
1425 {
1426     std::vector<int> v;
1427     template <typename... X>
VECVEC1428     VEC( X&&...x) : v(std::forward<X>(x)...) {}
1429 
1430     template <typename U, typename... X>
VECVEC1431     VEC(std::initializer_list<U> il, X&&...x) : v(il, std::forward<X>(x)...) {}
1432 };
1433 
1434 
1435 
main()1436 int main() {
1437   tr2::optional<int> oi = 1;
1438   assert (bool(oi));
1439   oi.operator=({});
1440   assert (!oi);
1441 
1442   VEC v = {5, 6};
1443 
1444   if (OPTIONAL_HAS_THIS_RVALUE_REFS)
1445     std::cout << "Optional has rvalue references for *this" << std::endl;
1446   else
1447     std::cout << "Optional doesn't have rvalue references for *this" << std::endl;
1448 
1449   if (OPTIONAL_HAS_CONSTEXPR_INIT_LIST)
1450     std::cout << "Optional has constexpr initializer_list" << std::endl;
1451   else
1452     std::cout << "Optional doesn't have constexpr initializer_list" << std::endl;
1453 
1454   if (OPTIONAL_HAS_MOVE_ACCESSORS)
1455     std::cout << "Optional has constexpr move accessors" << std::endl;
1456   else
1457     std::cout << "Optional doesn't have constexpr move accessors" << std::endl;
1458 }
1459 
1460