18 #include <lib/optional.h> 26 #include <momemta/Logging.h> 28 #include <platform/macros.h> 34 using momemta::gtl::nullopt;
36 using momemta::gtl::in_place;
38 using momemta::gtl::make_optional;
40 template <
typename T> std::string TypeQuals(T&) {
return "&"; }
41 template <
typename T> std::string TypeQuals(T&&) {
return "&&"; }
42 template <
typename T> std::string TypeQuals(
const T&) {
return "c&"; }
43 template <
typename T> std::string TypeQuals(
const T&&) {
return "c&&"; }
45 struct StructorListener {
58 static StructorListener* listener;
60 Listenable() { ++listener->construct0; }
61 Listenable(
int ) { ++listener->construct1; }
62 Listenable(
int ,
int ) { ++listener->construct2; }
63 Listenable(std::initializer_list<int> ) { ++listener->listinit; }
64 Listenable(
const Listenable& ) { ++listener->copy; }
65 Listenable(Listenable&& ) { ++listener->move; }
66 Listenable& operator=(
const Listenable& ) {
67 ++listener->copy_assign;
70 Listenable& operator=(Listenable&& ) {
71 ++listener->move_assign;
74 ~Listenable() { ++listener->destruct; }
77 StructorListener* Listenable::listener =
nullptr;
81 #if defined(__clang__) && defined(__APPLE__) 82 #define SKIP_CONSTEXPR_TEST_DUE_TO_CLANG_BUG 85 struct ConstexprType {
86 constexpr ConstexprType() : x(0) {}
87 constexpr
explicit ConstexprType(
int i) : x(i) {}
88 #ifndef SKIP_CONSTEXPR_TEST_DUE_TO_CLANG_BUG 89 constexpr ConstexprType(std::initializer_list<int> il) : x(il.size()) {}
91 constexpr ConstexprType(
const char* s ATTRIBUTE_UNUSED) : x(-1) {}
97 Copyable(
const Copyable&) {}
98 Copyable& operator=(
const Copyable&) {
return *
this; }
101 struct MoveableThrow {
103 MoveableThrow(MoveableThrow&&) {}
104 MoveableThrow& operator=(MoveableThrow&&) {
return *
this; }
107 struct MoveableNoThrow {
109 MoveableNoThrow(MoveableNoThrow&&) noexcept {}
110 MoveableNoThrow& operator=(MoveableNoThrow&&) noexcept {
return *
this; }
115 NonMovable(
const NonMovable&) =
delete;
116 NonMovable& operator=(
const NonMovable&) =
delete;
117 NonMovable(NonMovable&&) =
delete;
118 NonMovable& operator=(NonMovable&&) =
delete;
121 TEST_CASE(
"optional",
"[core/lib]") {
122 SECTION(
"DefaultConstructor")
125 REQUIRE_FALSE(!!empty);
126 constexpr optional<int> cempty;
127 static_assert(!cempty.has_value(),
"");
128 REQUIRE(std::is_nothrow_default_constructible<optional<int>>::value);
131 SECTION(
"NullOptConstructor")
133 optional<int> empty(nullopt);
134 REQUIRE_FALSE(!!empty);
137 constexpr optional<int> cempty{nullopt_t(nullopt_t::init)};
138 static_assert(!cempty.has_value(),
"");
139 REQUIRE((std::is_nothrow_constructible<optional<int>, nullopt_t>::value));
142 SECTION(
"CopyConstructor")
144 optional<int> empty, opt42 = 42;
145 optional<int> empty_copy(empty);
146 REQUIRE_FALSE(!!empty_copy);
147 optional<int> opt42_copy(opt42);
148 REQUIRE(!!opt42_copy);
149 REQUIRE(42 == opt42_copy);
151 REQUIRE(std::is_copy_constructible<optional<int>>::value);
152 REQUIRE(std::is_copy_constructible<optional<Copyable>>::value);
153 REQUIRE_FALSE(std::is_copy_constructible<optional<MoveableThrow>>::value);
154 REQUIRE_FALSE(std::is_copy_constructible<optional<MoveableNoThrow>>::value);
155 REQUIRE_FALSE(std::is_copy_constructible<optional<NonMovable>>::value);
158 SECTION(
"MoveConstructor")
160 optional<int> empty, opt42 = 42;
161 optional<int> empty_move(std::move(empty));
162 REQUIRE_FALSE(!!empty_move);
163 optional<int> opt42_move(std::move(opt42));
164 REQUIRE(!!opt42_move);
165 REQUIRE(42 == opt42_move);
167 REQUIRE(std::is_move_constructible<optional<int>>::value);
168 REQUIRE(std::is_move_constructible<optional<Copyable>>::value);
169 REQUIRE(std::is_move_constructible<optional<MoveableThrow>>::value);
170 REQUIRE(std::is_move_constructible<optional<MoveableNoThrow>>::value);
171 REQUIRE_FALSE(std::is_move_constructible<optional<NonMovable>>::value);
173 REQUIRE(std::is_nothrow_move_constructible<optional<int>>::value);
175 std::is_nothrow_move_constructible<optional<MoveableThrow>>::value);
177 std::is_nothrow_move_constructible<optional<MoveableNoThrow>>::value);
180 SECTION(
"Destructor")
188 REQUIRE(std::is_trivially_destructible<optional<int>>::value);
189 REQUIRE(std::is_trivially_destructible<optional<Trivial>>::value);
190 REQUIRE_FALSE(std::is_trivially_destructible<optional<NonTrivial>>::value);
193 SECTION(
"InPlaceConstructor")
195 constexpr optional<ConstexprType> opt0{in_place_t()};
196 static_assert(opt0,
"");
197 static_assert(opt0->x == 0,
"");
198 constexpr optional<ConstexprType> opt1{in_place_t(), 1};
199 static_assert(opt1,
"");
200 static_assert(opt1->x == 1,
"");
201 #ifndef SKIP_CONSTEXPR_TEST_DUE_TO_CLANG_BUG 202 constexpr optional<ConstexprType> opt2{in_place_t(), {1, 2}};
203 static_assert(opt2,
"");
204 static_assert(opt2->x == 2,
"");
219 SECTION(
"ValueConstructor")
221 constexpr optional<int> opt0(0);
222 static_assert(opt0,
"");
223 static_assert(*opt0 == 0,
"");
224 REQUIRE((std::is_convertible<
int, optional<int>>::value));
230 constexpr optional<ConstexprType> opt1 = {
"abc"};
231 static_assert(opt1,
"");
232 static_assert(-1 == opt1->x,
"");
234 (std::is_convertible<
const char *, optional<ConstexprType>>::value));
236 constexpr optional<ConstexprType> opt2{2};
237 static_assert(opt2,
"");
238 static_assert(2 == opt2->x,
"");
239 REQUIRE_FALSE((std::is_convertible<
int, optional<ConstexprType>>::value));
244 constexpr optional<int> opt3({});
245 static_assert(opt3,
"");
246 static_assert(*opt3 == 0,
"");
250 optional<ConstexprType> opt4({});
251 REQUIRE_FALSE(!!opt4);
259 Convert(
const Implicit&)
260 : implicit(true), move(false) {}
262 : implicit(true), move(true) {}
263 explicit Convert(
const Explicit&) : implicit(false), move(false) {}
264 explicit Convert(Explicit&&) : implicit(false), move(true) {}
270 struct ConvertFromOptional {
271 ConvertFromOptional(
const Implicit&)
272 : implicit(true), move(false), from_optional(false) {}
273 ConvertFromOptional(Implicit&&)
274 : implicit(true), move(true), from_optional(false) {}
275 ConvertFromOptional(
const optional<Implicit>&)
276 : implicit(true), move(false), from_optional(true) {}
277 ConvertFromOptional(optional<Implicit>&&)
278 : implicit(true), move(true), from_optional(true) {}
279 explicit ConvertFromOptional(
const Explicit&)
280 : implicit(false), move(false), from_optional(false) {}
281 explicit ConvertFromOptional(Explicit&&)
282 : implicit(false), move(true), from_optional(false) {}
283 explicit ConvertFromOptional(
const optional<Explicit>&)
284 : implicit(false), move(false), from_optional(true) {}
285 explicit ConvertFromOptional(optional<Explicit>&&)
286 : implicit(false), move(true), from_optional(true) {}
293 SECTION(
"ConvertingConstructor")
295 optional<Implicit> i_empty;
296 optional<Implicit> i(in_place);
297 optional<Explicit> e_empty;
298 optional<Explicit> e(in_place);
301 optional<Convert> empty = i_empty;
302 REQUIRE_FALSE(!!empty);
303 optional<Convert> opt_copy = i;
305 REQUIRE(opt_copy->implicit);
306 REQUIRE_FALSE(opt_copy->move);
307 optional<Convert> opt_move = optional<Implicit>(in_place);
309 REQUIRE(opt_move->implicit);
310 REQUIRE(opt_move->move);
314 optional<Convert> empty(e_empty);
315 REQUIRE_FALSE(!!empty);
316 optional<Convert> opt_copy(e);
318 REQUIRE_FALSE(opt_copy->implicit);
319 REQUIRE_FALSE(opt_copy->move);
320 REQUIRE_FALSE((std::is_convertible<
const optional<Explicit>&,
321 optional<Convert>>::value));
322 optional<Convert> opt_move{optional<Explicit>(in_place)};
324 REQUIRE_FALSE(opt_move->implicit);
325 REQUIRE(opt_move->move);
327 (std::is_convertible<optional<Explicit>&&, optional<Convert>>::value));
334 gtl::internal_optional::is_constructible_convertible_from_optional<
335 ConvertFromOptional, Implicit>::value,
337 optional<ConvertFromOptional> opt0 = i_empty;
339 REQUIRE(opt0->implicit);
340 REQUIRE_FALSE(opt0->move);
341 REQUIRE(opt0->from_optional);
342 optional<ConvertFromOptional> opt1 = optional<Implicit>();
344 REQUIRE(opt1->implicit);
346 REQUIRE(opt1->from_optional);
352 optional<ConvertFromOptional> opt0(e_empty);
354 REQUIRE_FALSE(opt0->implicit);
355 REQUIRE_FALSE(opt0->move);
356 REQUIRE(opt0->from_optional);
357 REQUIRE_FALSE((std::is_convertible<
const optional<Explicit>&,
358 optional<ConvertFromOptional>>::value));
359 optional<ConvertFromOptional> opt1{optional<Explicit>()};
361 REQUIRE_FALSE(opt1->implicit);
363 REQUIRE(opt1->from_optional);
364 REQUIRE_FALSE((std::is_convertible<optional<Explicit>&&,
365 optional<ConvertFromOptional>>::value));
369 SECTION(
"StructorBasic")
371 StructorListener listener;
372 Listenable::listener = &listener;
374 optional<Listenable> empty;
375 REQUIRE_FALSE(!!empty);
376 optional<Listenable> opt0(in_place);
378 optional<Listenable> opt1(in_place, 1);
380 optional<Listenable> opt2(in_place, 1, 2);
383 REQUIRE(1 == listener.construct0);
384 REQUIRE(1 == listener.construct1);
385 REQUIRE(1 == listener.construct2);
386 REQUIRE(3 == listener.destruct);
389 SECTION(
"CopyMoveStructor")
391 StructorListener listener;
392 Listenable::listener = &listener;
393 optional<Listenable> original(in_place);
394 REQUIRE(1 == listener.construct0);
395 REQUIRE(0 == listener.copy);
396 REQUIRE(0 == listener.move);
397 optional<Listenable> copy(original);
398 REQUIRE(1 == listener.construct0);
399 REQUIRE(1 == listener.copy);
400 REQUIRE(0 == listener.move);
401 optional<Listenable> move(std::move(original));
402 REQUIRE(1 == listener.construct0);
403 REQUIRE(1 == listener.copy);
404 REQUIRE(1 == listener.move);
409 StructorListener listener;
410 Listenable::listener = &listener;
411 optional<Listenable> listinit1(in_place, {1});
412 optional<Listenable> listinit2(in_place, {1, 2});
413 REQUIRE(2 == listener.listinit);
416 SECTION(
"AssignFromNullopt")
418 optional<int> opt(1);
420 REQUIRE_FALSE(!!opt);
422 StructorListener listener;
423 Listenable::listener = &listener;
424 optional<Listenable> opt1(in_place);
427 REQUIRE(1 == listener.construct0);
428 REQUIRE(1 == listener.destruct);
430 REQUIRE((std::is_nothrow_assignable<optional<int>, nullopt_t>::value));
432 (std::is_nothrow_assignable<optional<Listenable>, nullopt_t>::value));
435 SECTION(
"CopyAssignment")
437 const optional<int> empty, opt1 = 1, opt2 = 2;
438 optional<int> empty_to_opt1, opt1_to_opt2, opt2_to_empty;
440 REQUIRE_FALSE(!!empty_to_opt1);
441 empty_to_opt1 = empty;
442 REQUIRE_FALSE(!!empty_to_opt1);
443 empty_to_opt1 = opt1;
444 REQUIRE(!!empty_to_opt1);
445 REQUIRE(1 == empty_to_opt1.value());
447 REQUIRE_FALSE(!!opt1_to_opt2);
449 REQUIRE(!!opt1_to_opt2);
450 REQUIRE(1 == opt1_to_opt2.value());
452 REQUIRE(!!opt1_to_opt2);
453 REQUIRE(2 == opt1_to_opt2.value());
455 REQUIRE_FALSE(!!opt2_to_empty);
456 opt2_to_empty = opt2;
457 REQUIRE(!!opt2_to_empty);
458 REQUIRE(2 == opt2_to_empty.value());
459 opt2_to_empty = empty;
460 REQUIRE_FALSE(!!opt2_to_empty);
462 REQUIRE(std::is_copy_assignable<optional<Copyable>>::value);
463 REQUIRE_FALSE(std::is_copy_assignable<optional<MoveableThrow>>::value);
464 REQUIRE_FALSE(std::is_copy_assignable<optional<MoveableNoThrow>>::value);
465 REQUIRE_FALSE(std::is_copy_assignable<optional<NonMovable>>::value);
468 SECTION(
"MoveAssignment")
470 StructorListener listener;
471 Listenable::listener = &listener;
473 optional<Listenable> empty1, empty2, set1(in_place), set2(in_place);
474 REQUIRE(2 == listener.construct0);
475 optional<Listenable> empty_to_empty, empty_to_set, set_to_empty(in_place),
476 set_to_set(in_place);
477 REQUIRE(4 == listener.construct0);
478 empty_to_empty = std::move(empty1);
479 empty_to_set = std::move(set1);
480 set_to_empty = std::move(empty2);
481 set_to_set = std::move(set2);
482 REQUIRE(0 == listener.copy);
483 REQUIRE(1 == listener.move);
484 REQUIRE(1 == listener.destruct);
485 REQUIRE(1 == listener.move_assign);
487 REQUIRE(std::is_move_assignable<optional<Copyable>>::value);
488 REQUIRE(std::is_move_assignable<optional<MoveableThrow>>::value);
489 REQUIRE(std::is_move_assignable<optional<MoveableNoThrow>>::value);
490 REQUIRE_FALSE(std::is_move_assignable<optional<NonMovable>>::value);
492 REQUIRE_FALSE(std::is_nothrow_move_assignable<optional<MoveableThrow>>::value);
494 std::is_nothrow_move_assignable<optional<MoveableNoThrow>>::value);
497 struct NoConvertToOptional {
500 NoConvertToOptional(
const NoConvertToOptional&) =
delete;
504 CopyConvert(
const NoConvertToOptional&);
505 CopyConvert& operator=(
const CopyConvert&) =
delete;
506 CopyConvert& operator=(
const NoConvertToOptional&);
509 struct CopyConvertFromOptional {
510 CopyConvertFromOptional(
const NoConvertToOptional&);
511 CopyConvertFromOptional(
const optional<NoConvertToOptional>&);
512 CopyConvertFromOptional& operator=(
const CopyConvertFromOptional&) =
delete;
513 CopyConvertFromOptional& operator=(
const NoConvertToOptional&);
514 CopyConvertFromOptional& operator=(
const optional<NoConvertToOptional>&);
518 MoveConvert(NoConvertToOptional&&);
519 MoveConvert& operator=(
const MoveConvert&) =
delete;
520 MoveConvert& operator=(NoConvertToOptional&&);
523 struct MoveConvertFromOptional {
524 MoveConvertFromOptional(NoConvertToOptional&&);
525 MoveConvertFromOptional(optional<NoConvertToOptional>&&);
526 MoveConvertFromOptional& operator=(
const MoveConvertFromOptional&) =
delete;
527 MoveConvertFromOptional& operator=(NoConvertToOptional&&);
528 MoveConvertFromOptional& operator=(optional<NoConvertToOptional>&&);
532 SECTION(
"ValueAssignment")
535 REQUIRE_FALSE(!!opt);
538 REQUIRE(42 == opt.value());
540 REQUIRE_FALSE(!!opt);
543 REQUIRE(42 == opt.value());
546 REQUIRE(43 == opt.value());
548 REQUIRE_FALSE(!!opt);
552 REQUIRE(44 == opt.value());
555 REQUIRE((std::is_assignable<optional<CopyConvert>&,
556 const NoConvertToOptional&>::value));
558 REQUIRE((std::is_assignable<optional<CopyConvertFromOptional>&,
559 const NoConvertToOptional&>::value));
562 REQUIRE_FALSE((std::is_assignable<optional<MoveConvert>&,
563 const NoConvertToOptional&>::value));
565 REQUIRE((std::is_assignable<optional<MoveConvert>&,
566 NoConvertToOptional&&>::value));
570 REQUIRE_FALSE((std::is_assignable<optional<MoveConvertFromOptional>&,
571 const NoConvertToOptional&>::value));
573 REQUIRE((std::is_assignable<optional<MoveConvertFromOptional>&,
574 NoConvertToOptional&&>::value));
577 (std::is_assignable<optional<CopyConvertFromOptional>&,
578 const optional<NoConvertToOptional>&>::value));
580 REQUIRE((std::is_assignable<optional<MoveConvertFromOptional>&,
581 optional<NoConvertToOptional>&&>::value));
586 SECTION(
"ConvertingAssignment")
589 optional<char> opt_c(
'c');
592 REQUIRE(*opt_c == *opt_i);
593 opt_i = optional<char>();
594 REQUIRE_FALSE(!!opt_i);
595 opt_i = optional<char>(
'd');
597 REQUIRE(
'd' == *opt_i);
599 optional<std::string> opt_str;
600 optional<const char *> opt_cstr(
"abc");
603 REQUIRE(std::string(
"abc") == *opt_str);
604 opt_str = optional<const char *>();
605 REQUIRE_FALSE(!!opt_str);
606 opt_str = optional<const char *>(
"def");
608 REQUIRE(std::string(
"def") == *opt_str);
612 (std::is_assignable<optional<CopyConvert>,
613 const optional<NoConvertToOptional>&>::value));
618 (std::is_assignable<optional<MoveConvert>&,
619 const optional<NoConvertToOptional>&>::value));
621 REQUIRE((std::is_assignable<optional<MoveConvert>&,
622 optional<NoConvertToOptional>&&>::value));
630 (std::is_assignable<optional<MoveConvertFromOptional>&,
631 const optional<NoConvertToOptional>&>::value));
634 SECTION(
"ResetAndHasValue")
636 StructorListener listener;
637 Listenable::listener = &listener;
638 optional<Listenable> opt;
639 REQUIRE_FALSE(!!opt);
640 REQUIRE_FALSE(opt.has_value());
643 REQUIRE(opt.has_value());
645 REQUIRE_FALSE(!!opt);
646 REQUIRE_FALSE(opt.has_value());
647 REQUIRE(1 == listener.destruct);
649 REQUIRE_FALSE(!!opt);
650 REQUIRE_FALSE(opt.has_value());
652 constexpr optional<int> empty;
653 static_assert(!empty.has_value(),
"");
654 constexpr optional<int> nonempty(1);
655 static_assert(nonempty.has_value(),
"");
660 StructorListener listener;
661 Listenable::listener = &listener;
662 optional<Listenable> opt;
663 REQUIRE_FALSE(!!opt);
667 REQUIRE(1 == listener.construct1);
668 REQUIRE(1 == listener.construct2);
669 REQUIRE(1 == listener.destruct);
672 SECTION(
"ListEmplace")
674 StructorListener listener;
675 Listenable::listener = &listener;
676 optional<Listenable> opt;
677 REQUIRE_FALSE(!!opt);
681 REQUIRE(2 == listener.listinit);
682 REQUIRE(1 == listener.destruct);
687 optional<int> opt_empty, opt1 = 1, opt2 = 2;
688 REQUIRE_FALSE(!!opt_empty);
690 REQUIRE(1 == opt1.value());
692 REQUIRE(2 == opt2.value());
693 swap(opt_empty, opt1);
694 REQUIRE_FALSE(!!opt1);
695 REQUIRE(!!opt_empty);
696 REQUIRE(1 == opt_empty.value());
698 REQUIRE(2 == opt2.value());
699 swap(opt_empty, opt1);
700 REQUIRE_FALSE(!!opt_empty);
702 REQUIRE(1 == opt1.value());
704 REQUIRE(2 == opt2.value());
706 REQUIRE_FALSE(!!opt_empty);
708 REQUIRE(2 == opt1.value());
710 REQUIRE(1 == opt2.value());
712 REQUIRE(noexcept(opt1.swap(opt2)));
713 REQUIRE(noexcept(swap(opt1, opt2)));
716 SECTION(
"PointerStuff")
718 optional<std::string> opt(in_place,
"foo");
719 REQUIRE(
"foo" == *opt);
720 const auto& opt_const = opt;
721 REQUIRE(
"foo" == *opt_const);
722 REQUIRE(opt->size() == 3);
723 REQUIRE(opt_const->size() == 3);
725 constexpr optional<ConstexprType> opt1(1);
726 static_assert(opt1->x == 1,
"");
732 #if defined(__GNUC__) && !defined(__clang__) 733 #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 9) 734 #define SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG 740 using O = optional<std::string>;
741 using CO =
const optional<std::string>;
742 O lvalue(in_place,
"lvalue");
743 CO clvalue(in_place,
"clvalue");
744 REQUIRE(
"lvalue" == lvalue.value());
745 REQUIRE(
"clvalue" == clvalue.value());
746 REQUIRE(
"xvalue" == O(in_place,
"xvalue").value());
747 #ifndef SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG 748 REQUIRE(
"cxvalue" == CO(in_place,
"cxvalue").value());
749 REQUIRE(
"&" == TypeQuals(lvalue.value()));
750 REQUIRE(
"c&" == TypeQuals(clvalue.value()));
751 REQUIRE(
"&&" == TypeQuals(O(in_place,
"xvalue").value()));
752 REQUIRE(
"c&&" == TypeQuals(CO(in_place,
"cxvalue").value()));
756 SECTION(
"DerefOperator")
758 using O = optional<std::string>;
759 using CO =
const optional<std::string>;
760 O lvalue(in_place,
"lvalue");
761 CO clvalue(in_place,
"clvalue");
762 REQUIRE(
"lvalue" == *lvalue);
763 REQUIRE(
"clvalue" == *clvalue);
764 REQUIRE(
"xvalue" == *O(in_place,
"xvalue"));
765 #ifndef SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG 766 REQUIRE(
"cxvalue" == *CO(in_place,
"cxvalue"));
767 REQUIRE(
"&" == TypeQuals(*lvalue));
768 REQUIRE(
"c&" == TypeQuals(*clvalue));
769 REQUIRE(
"&&" == TypeQuals(*O(in_place,
"xvalue")));
770 REQUIRE(
"c&&" == TypeQuals(*CO(in_place,
"cxvalue")));
773 constexpr optional<int> opt1(1);
774 static_assert(*opt1 == 1,
"");
776 #if !defined(SKIP_CONSTEXPR_TEST_DUE_TO_CLANG_BUG) && \ 777 !defined(SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG) 778 using COI =
const optional<int>;
779 static_assert(*COI(2) == 2,
"");
785 optional<double> opt_empty, opt_set = 1.2;
786 REQUIRE(42.0 == opt_empty.value_or(42));
787 REQUIRE(1.2 == opt_set.value_or(42));
788 REQUIRE(42.0 == optional<double>().value_or(42));
789 REQUIRE(1.2 == optional<double>(1.2).value_or(42));
791 #ifndef SKIP_CONSTEXPR_TEST_DUE_TO_CLANG_BUG 792 constexpr optional<double> copt_empty;
793 static_assert(42.0 == copt_empty.value_or(42),
"");
795 constexpr optional<double> copt_set = {1.2};
796 static_assert(1.2 == copt_set.value_or(42),
"");
798 using COD =
const optional<double>;
799 static_assert(42.0 == COD().value_or(42),
"");
800 static_assert(1.2 == COD(1.2).value_or(42),
"");
805 SECTION(
"make_optional")
807 auto opt_int = make_optional(42);
808 REQUIRE((std::is_same<decltype(opt_int), optional<int>>::value));
809 REQUIRE(42 == opt_int);
811 StructorListener listener;
812 Listenable::listener = &listener;
814 optional<Listenable> opt0 = make_optional<Listenable>();
815 REQUIRE(1 == listener.construct0);
816 optional<Listenable> opt1 = make_optional<Listenable>(1);
817 REQUIRE(1 == listener.construct1);
818 optional<Listenable> opt2 = make_optional<Listenable>(1, 2);
819 REQUIRE(1 == listener.construct2);
820 optional<Listenable> opt3 = make_optional<Listenable>({1});
821 optional<Listenable> opt4 = make_optional<Listenable>({1, 2});
822 REQUIRE(2 == listener.listinit);
825 SECTION(
"Comparisons")
827 optional<int> ae, be, a2 = 2, b2 = 2, a4 = 4, b4 = 4;
829 #define optionalTest_Comparisons_EXPECT_LESS(x, y) \ 830 REQUIRE_FALSE((x) == (y)); \ 831 REQUIRE((x) != (y)); \ 832 REQUIRE((x) < (y)); \ 833 REQUIRE_FALSE((x) > (y)); \ 834 REQUIRE((x) <= (y)); \ 835 REQUIRE_FALSE((x) >= (y)); 837 #define optionalTest_Comparisons_EXPECT_SAME(x, y) \ 838 REQUIRE((x) == (y)); \ 839 REQUIRE_FALSE((x) != (y)); \ 840 REQUIRE_FALSE((x) < (y)); \ 841 REQUIRE_FALSE((x) > (y)); \ 842 REQUIRE((x) <= (y)); \ 845 #define optionalTest_Comparisons_EXPECT_GREATER(x, y) \ 846 REQUIRE_FALSE((x) == (y)); \ 847 REQUIRE((x) != (y)); \ 848 REQUIRE_FALSE((x) < (y)); \ 849 REQUIRE((x) > (y)); \ 850 REQUIRE_FALSE((x) <= (y)); \ 857 optionalTest_Comparisons_EXPECT_SAME(nullopt, be);
858 optionalTest_Comparisons_EXPECT_LESS(nullopt, b2);
860 optionalTest_Comparisons_EXPECT_LESS(nullopt, b4);
862 optionalTest_Comparisons_EXPECT_SAME(ae, nullopt);
863 optionalTest_Comparisons_EXPECT_SAME(ae, be);
864 optionalTest_Comparisons_EXPECT_LESS(ae, b2);
865 optionalTest_Comparisons_EXPECT_LESS(ae, 3);
866 optionalTest_Comparisons_EXPECT_LESS(ae, b4);
868 optionalTest_Comparisons_EXPECT_GREATER(a2, nullopt);
869 optionalTest_Comparisons_EXPECT_GREATER(a2, be);
870 optionalTest_Comparisons_EXPECT_SAME(a2, b2);
871 optionalTest_Comparisons_EXPECT_LESS(a2, 3);
872 optionalTest_Comparisons_EXPECT_LESS(a2, b4);
875 optionalTest_Comparisons_EXPECT_GREATER(3, be);
876 optionalTest_Comparisons_EXPECT_GREATER(3, b2);
877 optionalTest_Comparisons_EXPECT_SAME(3, 3);
878 optionalTest_Comparisons_EXPECT_LESS(3, b4);
880 optionalTest_Comparisons_EXPECT_GREATER(a4, nullopt);
881 optionalTest_Comparisons_EXPECT_GREATER(a4, be);
882 optionalTest_Comparisons_EXPECT_GREATER(a4, b2);
883 optionalTest_Comparisons_EXPECT_GREATER(a4, 3);
884 optionalTest_Comparisons_EXPECT_SAME(a4, b4);
887 SECTION(
"SwapRegression")
889 StructorListener listener;
890 Listenable::listener = &listener;
893 optional<Listenable> a;
894 optional<Listenable> b(in_place);
898 REQUIRE(1 == listener.construct0);
899 REQUIRE(1 == listener.move);
900 REQUIRE(2 == listener.destruct);
903 optional<Listenable> a(in_place);
904 optional<Listenable> b;
908 REQUIRE(2 == listener.construct0);
909 REQUIRE(2 == listener.move);
910 REQUIRE(4 == listener.destruct);
913 SECTION(
"BigStringLeakCheck")
915 constexpr
size_t n = 1 << 16;
917 using OS = optional<std::string>;
921 OS c = std::string(n,
'c');
922 std::string sd(n,
'd');
924 OS e(in_place, n,
'e');
936 OS oc = std::string(n,
'c');
937 std::string sod(n,
'd');
939 OS oe(in_place, n,
'e');
943 OS ma(std::move(oa));
944 OS mb(std::move(ob));
945 OS mc(std::move(oc));
946 OS md(std::move(od));
947 OS me(std::move(oe));
948 OS mf(std::move(of));
952 OS ac1 = std::string(n,
'c');
953 std::string sad1(n,
'd');
955 OS ae1(in_place, n,
'e');
961 OS ac2 = std::string(n,
'c');
962 std::string sad2(n,
'd');
964 OS ae2(in_place, n,
'e');
977 OS ac3 = std::string(n,
'c');
978 std::string sad3(n,
'd');
980 OS ae3(in_place, n,
'e');
993 OS ac4 = std::string(n,
'c');
994 std::string sad4(n,
'd');
996 OS ae4(in_place, n,
'e');
1000 aa4 = OS(in_place, n,
'a');
1001 ab4 = OS(in_place, n,
'b');
1002 ac4 = OS(in_place, n,
'c');
1003 ad4 = OS(in_place, n,
'd');
1004 ae4 = OS(in_place, n,
'e');
1005 af4 = OS(in_place, n,
'f');
1009 OS ac5 = std::string(n,
'c');
1010 std::string sad5(n,
'd');
1012 OS ae5(in_place, n,
'e');
1014 af5.emplace(n,
'f');
1016 std::string saa5(n,
'a');
1017 std::string sab5(n,
'a');
1018 std::string sac5(n,
'a');
1019 std::string sad52(n,
'a');
1020 std::string sae5(n,
'a');
1021 std::string saf5(n,
'a');
1032 OS ac6 = std::string(n,
'c');
1033 std::string sad6(n,
'd');
1035 OS ae6(in_place, n,
'e');
1037 af6.emplace(n,
'f');
1039 aa6 = std::string(n,
'a');
1040 ab6 = std::string(n,
'b');
1041 ac6 = std::string(n,
'c');
1042 ad6 = std::string(n,
'd');
1043 ae6 = std::string(n,
'e');
1044 af6 = std::string(n,
'f');
1048 OS ac7 = std::string(n,
'c');
1049 std::string sad7(n,
'd');
1051 OS ae7(in_place, n,
'e');
1053 af7.emplace(n,
'f');
1055 aa7.emplace(n,
'A');
1056 ab7.emplace(n,
'B');
1057 ac7.emplace(n,
'C');
1058 ad7.emplace(n,
'D');
1059 ae7.emplace(n,
'E');
1060 af7.emplace(n,
'F');
1063 SECTION(
"MoveAssignRegression")
1065 StructorListener listener;
1066 Listenable::listener = &listener;
1069 optional<Listenable> a;
1074 REQUIRE(1 == listener.construct0);
1075 REQUIRE(1 == listener.move);
1076 REQUIRE(2 == listener.destruct);
1079 SECTION(
"ValueType")
1081 REQUIRE((std::is_same<optional<int>::value_type,
int>::value));
1082 REQUIRE((std::is_same<optional<std::string>::value_type, std::string>::value));
1083 REQUIRE_FALSE((std::is_same<optional<int>::value_type, nullopt_t>::value));
1088 std::hash<optional<int>> hash;
1089 std::set<size_t> hashcodes;
1090 hashcodes.insert(hash(nullopt));
1091 for (
int i = 0; i < 100; ++i) {
1092 hashcodes.insert(hash(i));
1094 REQUIRE(hashcodes.size() > 90);
1097 struct MoveMeNoThrow {
1098 MoveMeNoThrow() : x(0) {}
1099 MoveMeNoThrow(
const MoveMeNoThrow& other) : x(other.x) {
1100 LOG(fatal) <<
"Should not be called.";
1102 MoveMeNoThrow(MoveMeNoThrow&& other) noexcept : x(other.x) {}
1106 struct MoveMeThrow {
1107 MoveMeThrow() : x(0) {}
1108 MoveMeThrow(
const MoveMeThrow& other) : x(other.x) {}
1109 MoveMeThrow(MoveMeThrow&& other) : x(other.x) {}
1116 std::is_nothrow_move_constructible<optional<MoveMeNoThrow>>::value,
"");
1118 !std::is_nothrow_move_constructible<optional<MoveMeThrow>>::value,
"");
1119 std::vector<optional<MoveMeNoThrow>> v;
1120 for (
int i = 0; i < 10; ++i)