18 #include <lib/optional.h> 25 #include <momemta/Logging.h> 27 #include <platform/macros.h> 33 using momemta::gtl::nullopt;
35 using momemta::gtl::in_place;
37 using momemta::gtl::make_optional;
39 template <
typename T> std::string TypeQuals(T&) {
return "&"; }
40 template <
typename T> std::string TypeQuals(T&&) {
return "&&"; }
41 template <
typename T> std::string TypeQuals(
const T&) {
return "c&"; }
42 template <
typename T> std::string TypeQuals(
const T&&) {
return "c&&"; }
44 struct StructorListener {
57 static StructorListener* listener;
59 Listenable() { ++listener->construct0; }
60 Listenable(
int ) { ++listener->construct1; }
61 Listenable(
int ,
int ) { ++listener->construct2; }
62 Listenable(std::initializer_list<int> ) { ++listener->listinit; }
63 Listenable(
const Listenable& ) { ++listener->copy; }
64 Listenable(Listenable&& ) { ++listener->move; }
65 Listenable& operator=(
const Listenable& ) {
66 ++listener->copy_assign;
69 Listenable& operator=(Listenable&& ) {
70 ++listener->move_assign;
73 ~Listenable() { ++listener->destruct; }
76 StructorListener* Listenable::listener =
nullptr;
80 #if defined(__clang__) && defined(__APPLE__) 81 #define SKIP_CONSTEXPR_TEST_DUE_TO_CLANG_BUG 84 struct ConstexprType {
85 constexpr ConstexprType() : x(0) {}
86 constexpr
explicit ConstexprType(
int i) : x(i) {}
87 #ifndef SKIP_CONSTEXPR_TEST_DUE_TO_CLANG_BUG 88 constexpr ConstexprType(std::initializer_list<int> il) : x(il.size()) {}
90 constexpr ConstexprType(
const char* s ATTRIBUTE_UNUSED) : x(-1) {}
96 Copyable(
const Copyable&) {}
97 Copyable& operator=(
const Copyable&) {
return *
this; }
100 struct MoveableThrow {
102 MoveableThrow(MoveableThrow&&) {}
103 MoveableThrow& operator=(MoveableThrow&&) {
return *
this; }
106 struct MoveableNoThrow {
108 MoveableNoThrow(MoveableNoThrow&&) noexcept {}
109 MoveableNoThrow& operator=(MoveableNoThrow&&) noexcept {
return *
this; }
114 NonMovable(
const NonMovable&) =
delete;
115 NonMovable& operator=(
const NonMovable&) =
delete;
116 NonMovable(NonMovable&&) =
delete;
117 NonMovable& operator=(NonMovable&&) =
delete;
120 TEST_CASE(
"optional",
"[core/lib]") {
121 SECTION(
"DefaultConstructor")
124 REQUIRE_FALSE(!!empty);
125 constexpr optional<int> cempty;
126 static_assert(!cempty.has_value(),
"");
127 REQUIRE(std::is_nothrow_default_constructible<optional<int>>::value);
130 SECTION(
"NullOptConstructor")
132 optional<int> empty(nullopt);
133 REQUIRE_FALSE(!!empty);
136 constexpr optional<int> cempty{nullopt_t(nullopt_t::init)};
137 static_assert(!cempty.has_value(),
"");
138 REQUIRE((std::is_nothrow_constructible<optional<int>, nullopt_t>::value));
141 SECTION(
"CopyConstructor")
143 optional<int> empty, opt42 = 42;
144 optional<int> empty_copy(empty);
145 REQUIRE_FALSE(!!empty_copy);
146 optional<int> opt42_copy(opt42);
147 REQUIRE(!!opt42_copy);
148 REQUIRE(42 == opt42_copy);
150 REQUIRE(std::is_copy_constructible<optional<int>>::value);
151 REQUIRE(std::is_copy_constructible<optional<Copyable>>::value);
152 REQUIRE_FALSE(std::is_copy_constructible<optional<MoveableThrow>>::value);
153 REQUIRE_FALSE(std::is_copy_constructible<optional<MoveableNoThrow>>::value);
154 REQUIRE_FALSE(std::is_copy_constructible<optional<NonMovable>>::value);
157 SECTION(
"MoveConstructor")
159 optional<int> empty, opt42 = 42;
160 optional<int> empty_move(std::move(empty));
161 REQUIRE_FALSE(!!empty_move);
162 optional<int> opt42_move(std::move(opt42));
163 REQUIRE(!!opt42_move);
164 REQUIRE(42 == opt42_move);
166 REQUIRE(std::is_move_constructible<optional<int>>::value);
167 REQUIRE(std::is_move_constructible<optional<Copyable>>::value);
168 REQUIRE(std::is_move_constructible<optional<MoveableThrow>>::value);
169 REQUIRE(std::is_move_constructible<optional<MoveableNoThrow>>::value);
170 REQUIRE_FALSE(std::is_move_constructible<optional<NonMovable>>::value);
172 REQUIRE(std::is_nothrow_move_constructible<optional<int>>::value);
174 std::is_nothrow_move_constructible<optional<MoveableThrow>>::value);
176 std::is_nothrow_move_constructible<optional<MoveableNoThrow>>::value);
179 SECTION(
"Destructor")
187 REQUIRE(std::is_trivially_destructible<optional<int>>::value);
188 REQUIRE(std::is_trivially_destructible<optional<Trivial>>::value);
189 REQUIRE_FALSE(std::is_trivially_destructible<optional<NonTrivial>>::value);
192 SECTION(
"InPlaceConstructor")
194 constexpr optional<ConstexprType> opt0{in_place_t()};
195 static_assert(opt0,
"");
196 static_assert(opt0->x == 0,
"");
197 constexpr optional<ConstexprType> opt1{in_place_t(), 1};
198 static_assert(opt1,
"");
199 static_assert(opt1->x == 1,
"");
200 #ifndef SKIP_CONSTEXPR_TEST_DUE_TO_CLANG_BUG 201 constexpr optional<ConstexprType> opt2{in_place_t(), {1, 2}};
202 static_assert(opt2,
"");
203 static_assert(opt2->x == 2,
"");
218 SECTION(
"ValueConstructor")
220 constexpr optional<int> opt0(0);
221 static_assert(opt0,
"");
222 static_assert(*opt0 == 0,
"");
223 REQUIRE((std::is_convertible<
int, optional<int>>::value));
229 constexpr optional<ConstexprType> opt1 = {
"abc"};
230 static_assert(opt1,
"");
231 static_assert(-1 == opt1->x,
"");
233 (std::is_convertible<
const char *, optional<ConstexprType>>::value));
235 constexpr optional<ConstexprType> opt2{2};
236 static_assert(opt2,
"");
237 static_assert(2 == opt2->x,
"");
238 REQUIRE_FALSE((std::is_convertible<
int, optional<ConstexprType>>::value));
243 constexpr optional<int> opt3({});
244 static_assert(opt3,
"");
245 static_assert(*opt3 == 0,
"");
249 optional<ConstexprType> opt4({});
250 REQUIRE_FALSE(!!opt4);
258 Convert(
const Implicit&)
259 : implicit(true), move(false) {}
261 : implicit(true), move(true) {}
262 explicit Convert(
const Explicit&) : implicit(false), move(false) {}
263 explicit Convert(Explicit&&) : implicit(false), move(true) {}
269 struct ConvertFromOptional {
270 ConvertFromOptional(
const Implicit&)
271 : implicit(true), move(false), from_optional(false) {}
272 ConvertFromOptional(Implicit&&)
273 : implicit(true), move(true), from_optional(false) {}
274 ConvertFromOptional(
const optional<Implicit>&)
275 : implicit(true), move(false), from_optional(true) {}
276 ConvertFromOptional(optional<Implicit>&&)
277 : implicit(true), move(true), from_optional(true) {}
278 explicit ConvertFromOptional(
const Explicit&)
279 : implicit(false), move(false), from_optional(false) {}
280 explicit ConvertFromOptional(Explicit&&)
281 : implicit(false), move(true), from_optional(false) {}
282 explicit ConvertFromOptional(
const optional<Explicit>&)
283 : implicit(false), move(false), from_optional(true) {}
284 explicit ConvertFromOptional(optional<Explicit>&&)
285 : implicit(false), move(true), from_optional(true) {}
292 SECTION(
"ConvertingConstructor")
294 optional<Implicit> i_empty;
295 optional<Implicit> i(in_place);
296 optional<Explicit> e_empty;
297 optional<Explicit> e(in_place);
300 optional<Convert> empty = i_empty;
301 REQUIRE_FALSE(!!empty);
302 optional<Convert> opt_copy = i;
304 REQUIRE(opt_copy->implicit);
305 REQUIRE_FALSE(opt_copy->move);
306 optional<Convert> opt_move = optional<Implicit>(in_place);
308 REQUIRE(opt_move->implicit);
309 REQUIRE(opt_move->move);
313 optional<Convert> empty(e_empty);
314 REQUIRE_FALSE(!!empty);
315 optional<Convert> opt_copy(e);
317 REQUIRE_FALSE(opt_copy->implicit);
318 REQUIRE_FALSE(opt_copy->move);
319 REQUIRE_FALSE((std::is_convertible<
const optional<Explicit>&,
320 optional<Convert>>::value));
321 optional<Convert> opt_move{optional<Explicit>(in_place)};
323 REQUIRE_FALSE(opt_move->implicit);
324 REQUIRE(opt_move->move);
326 (std::is_convertible<optional<Explicit>&&, optional<Convert>>::value));
333 gtl::internal_optional::is_constructible_convertible_from_optional<
334 ConvertFromOptional, Implicit>::value,
336 optional<ConvertFromOptional> opt0 = i_empty;
338 REQUIRE(opt0->implicit);
339 REQUIRE_FALSE(opt0->move);
340 REQUIRE(opt0->from_optional);
341 optional<ConvertFromOptional> opt1 = optional<Implicit>();
343 REQUIRE(opt1->implicit);
345 REQUIRE(opt1->from_optional);
351 optional<ConvertFromOptional> opt0(e_empty);
353 REQUIRE_FALSE(opt0->implicit);
354 REQUIRE_FALSE(opt0->move);
355 REQUIRE(opt0->from_optional);
356 REQUIRE_FALSE((std::is_convertible<
const optional<Explicit>&,
357 optional<ConvertFromOptional>>::value));
358 optional<ConvertFromOptional> opt1{optional<Explicit>()};
360 REQUIRE_FALSE(opt1->implicit);
362 REQUIRE(opt1->from_optional);
363 REQUIRE_FALSE((std::is_convertible<optional<Explicit>&&,
364 optional<ConvertFromOptional>>::value));
368 SECTION(
"StructorBasic")
370 StructorListener listener;
371 Listenable::listener = &listener;
373 optional<Listenable> empty;
374 REQUIRE_FALSE(!!empty);
375 optional<Listenable> opt0(in_place);
377 optional<Listenable> opt1(in_place, 1);
379 optional<Listenable> opt2(in_place, 1, 2);
382 REQUIRE(1 == listener.construct0);
383 REQUIRE(1 == listener.construct1);
384 REQUIRE(1 == listener.construct2);
385 REQUIRE(3 == listener.destruct);
388 SECTION(
"CopyMoveStructor")
390 StructorListener listener;
391 Listenable::listener = &listener;
392 optional<Listenable> original(in_place);
393 REQUIRE(1 == listener.construct0);
394 REQUIRE(0 == listener.copy);
395 REQUIRE(0 == listener.move);
396 optional<Listenable> copy(original);
397 REQUIRE(1 == listener.construct0);
398 REQUIRE(1 == listener.copy);
399 REQUIRE(0 == listener.move);
400 optional<Listenable> move(std::move(original));
401 REQUIRE(1 == listener.construct0);
402 REQUIRE(1 == listener.copy);
403 REQUIRE(1 == listener.move);
408 StructorListener listener;
409 Listenable::listener = &listener;
410 optional<Listenable> listinit1(in_place, {1});
411 optional<Listenable> listinit2(in_place, {1, 2});
412 REQUIRE(2 == listener.listinit);
415 SECTION(
"AssignFromNullopt")
417 optional<int> opt(1);
419 REQUIRE_FALSE(!!opt);
421 StructorListener listener;
422 Listenable::listener = &listener;
423 optional<Listenable> opt1(in_place);
426 REQUIRE(1 == listener.construct0);
427 REQUIRE(1 == listener.destruct);
429 REQUIRE((std::is_nothrow_assignable<optional<int>, nullopt_t>::value));
431 (std::is_nothrow_assignable<optional<Listenable>, nullopt_t>::value));
434 SECTION(
"CopyAssignment")
436 const optional<int> empty, opt1 = 1, opt2 = 2;
437 optional<int> empty_to_opt1, opt1_to_opt2, opt2_to_empty;
439 REQUIRE_FALSE(!!empty_to_opt1);
440 empty_to_opt1 = empty;
441 REQUIRE_FALSE(!!empty_to_opt1);
442 empty_to_opt1 = opt1;
443 REQUIRE(!!empty_to_opt1);
444 REQUIRE(1 == empty_to_opt1.value());
446 REQUIRE_FALSE(!!opt1_to_opt2);
448 REQUIRE(!!opt1_to_opt2);
449 REQUIRE(1 == opt1_to_opt2.value());
451 REQUIRE(!!opt1_to_opt2);
452 REQUIRE(2 == opt1_to_opt2.value());
454 REQUIRE_FALSE(!!opt2_to_empty);
455 opt2_to_empty = opt2;
456 REQUIRE(!!opt2_to_empty);
457 REQUIRE(2 == opt2_to_empty.value());
458 opt2_to_empty = empty;
459 REQUIRE_FALSE(!!opt2_to_empty);
461 REQUIRE(std::is_copy_assignable<optional<Copyable>>::value);
462 REQUIRE_FALSE(std::is_copy_assignable<optional<MoveableThrow>>::value);
463 REQUIRE_FALSE(std::is_copy_assignable<optional<MoveableNoThrow>>::value);
464 REQUIRE_FALSE(std::is_copy_assignable<optional<NonMovable>>::value);
467 SECTION(
"MoveAssignment")
469 StructorListener listener;
470 Listenable::listener = &listener;
472 optional<Listenable> empty1, empty2, set1(in_place), set2(in_place);
473 REQUIRE(2 == listener.construct0);
474 optional<Listenable> empty_to_empty, empty_to_set, set_to_empty(in_place),
475 set_to_set(in_place);
476 REQUIRE(4 == listener.construct0);
477 empty_to_empty = std::move(empty1);
478 empty_to_set = std::move(set1);
479 set_to_empty = std::move(empty2);
480 set_to_set = std::move(set2);
481 REQUIRE(0 == listener.copy);
482 REQUIRE(1 == listener.move);
483 REQUIRE(1 == listener.destruct);
484 REQUIRE(1 == listener.move_assign);
486 REQUIRE(std::is_move_assignable<optional<Copyable>>::value);
487 REQUIRE(std::is_move_assignable<optional<MoveableThrow>>::value);
488 REQUIRE(std::is_move_assignable<optional<MoveableNoThrow>>::value);
489 REQUIRE_FALSE(std::is_move_assignable<optional<NonMovable>>::value);
491 REQUIRE_FALSE(std::is_nothrow_move_assignable<optional<MoveableThrow>>::value);
493 std::is_nothrow_move_assignable<optional<MoveableNoThrow>>::value);
496 struct NoConvertToOptional {
499 NoConvertToOptional(
const NoConvertToOptional&) =
delete;
503 CopyConvert(
const NoConvertToOptional&);
504 CopyConvert& operator=(
const CopyConvert&) =
delete;
505 CopyConvert& operator=(
const NoConvertToOptional&);
508 struct CopyConvertFromOptional {
509 CopyConvertFromOptional(
const NoConvertToOptional&);
510 CopyConvertFromOptional(
const optional<NoConvertToOptional>&);
511 CopyConvertFromOptional& operator=(
const CopyConvertFromOptional&) =
delete;
512 CopyConvertFromOptional& operator=(
const NoConvertToOptional&);
513 CopyConvertFromOptional& operator=(
const optional<NoConvertToOptional>&);
517 MoveConvert(NoConvertToOptional&&);
518 MoveConvert& operator=(
const MoveConvert&) =
delete;
519 MoveConvert& operator=(NoConvertToOptional&&);
522 struct MoveConvertFromOptional {
523 MoveConvertFromOptional(NoConvertToOptional&&);
524 MoveConvertFromOptional(optional<NoConvertToOptional>&&);
525 MoveConvertFromOptional& operator=(
const MoveConvertFromOptional&) =
delete;
526 MoveConvertFromOptional& operator=(NoConvertToOptional&&);
527 MoveConvertFromOptional& operator=(optional<NoConvertToOptional>&&);
531 SECTION(
"ValueAssignment")
534 REQUIRE_FALSE(!!opt);
537 REQUIRE(42 == opt.value());
539 REQUIRE_FALSE(!!opt);
542 REQUIRE(42 == opt.value());
545 REQUIRE(43 == opt.value());
547 REQUIRE_FALSE(!!opt);
551 REQUIRE(44 == opt.value());
554 REQUIRE((std::is_assignable<optional<CopyConvert>&,
555 const NoConvertToOptional&>::value));
557 REQUIRE((std::is_assignable<optional<CopyConvertFromOptional>&,
558 const NoConvertToOptional&>::value));
561 REQUIRE_FALSE((std::is_assignable<optional<MoveConvert>&,
562 const NoConvertToOptional&>::value));
564 REQUIRE((std::is_assignable<optional<MoveConvert>&,
565 NoConvertToOptional&&>::value));
569 REQUIRE_FALSE((std::is_assignable<optional<MoveConvertFromOptional>&,
570 const NoConvertToOptional&>::value));
572 REQUIRE((std::is_assignable<optional<MoveConvertFromOptional>&,
573 NoConvertToOptional&&>::value));
576 (std::is_assignable<optional<CopyConvertFromOptional>&,
577 const optional<NoConvertToOptional>&>::value));
579 REQUIRE((std::is_assignable<optional<MoveConvertFromOptional>&,
580 optional<NoConvertToOptional>&&>::value));
585 SECTION(
"ConvertingAssignment")
588 optional<char> opt_c(
'c');
591 REQUIRE(*opt_c == *opt_i);
592 opt_i = optional<char>();
593 REQUIRE_FALSE(!!opt_i);
594 opt_i = optional<char>(
'd');
596 REQUIRE(
'd' == *opt_i);
598 optional<std::string> opt_str;
599 optional<const char *> opt_cstr(
"abc");
602 REQUIRE(std::string(
"abc") == *opt_str);
603 opt_str = optional<const char *>();
604 REQUIRE_FALSE(!!opt_str);
605 opt_str = optional<const char *>(
"def");
607 REQUIRE(std::string(
"def") == *opt_str);
611 (std::is_assignable<optional<CopyConvert>,
612 const optional<NoConvertToOptional>&>::value));
617 (std::is_assignable<optional<MoveConvert>&,
618 const optional<NoConvertToOptional>&>::value));
620 REQUIRE((std::is_assignable<optional<MoveConvert>&,
621 optional<NoConvertToOptional>&&>::value));
629 (std::is_assignable<optional<MoveConvertFromOptional>&,
630 const optional<NoConvertToOptional>&>::value));
633 SECTION(
"ResetAndHasValue")
635 StructorListener listener;
636 Listenable::listener = &listener;
637 optional<Listenable> opt;
638 REQUIRE_FALSE(!!opt);
639 REQUIRE_FALSE(opt.has_value());
642 REQUIRE(opt.has_value());
644 REQUIRE_FALSE(!!opt);
645 REQUIRE_FALSE(opt.has_value());
646 REQUIRE(1 == listener.destruct);
648 REQUIRE_FALSE(!!opt);
649 REQUIRE_FALSE(opt.has_value());
651 constexpr optional<int> empty;
652 static_assert(!empty.has_value(),
"");
653 constexpr optional<int> nonempty(1);
654 static_assert(nonempty.has_value(),
"");
659 StructorListener listener;
660 Listenable::listener = &listener;
661 optional<Listenable> opt;
662 REQUIRE_FALSE(!!opt);
666 REQUIRE(1 == listener.construct1);
667 REQUIRE(1 == listener.construct2);
668 REQUIRE(1 == listener.destruct);
671 SECTION(
"ListEmplace")
673 StructorListener listener;
674 Listenable::listener = &listener;
675 optional<Listenable> opt;
676 REQUIRE_FALSE(!!opt);
680 REQUIRE(2 == listener.listinit);
681 REQUIRE(1 == listener.destruct);
686 optional<int> opt_empty, opt1 = 1, opt2 = 2;
687 REQUIRE_FALSE(!!opt_empty);
689 REQUIRE(1 == opt1.value());
691 REQUIRE(2 == opt2.value());
692 swap(opt_empty, opt1);
693 REQUIRE_FALSE(!!opt1);
694 REQUIRE(!!opt_empty);
695 REQUIRE(1 == opt_empty.value());
697 REQUIRE(2 == opt2.value());
698 swap(opt_empty, opt1);
699 REQUIRE_FALSE(!!opt_empty);
701 REQUIRE(1 == opt1.value());
703 REQUIRE(2 == opt2.value());
705 REQUIRE_FALSE(!!opt_empty);
707 REQUIRE(2 == opt1.value());
709 REQUIRE(1 == opt2.value());
711 REQUIRE(noexcept(opt1.swap(opt2)));
712 REQUIRE(noexcept(swap(opt1, opt2)));
715 SECTION(
"PointerStuff")
717 optional<std::string> opt(in_place,
"foo");
718 REQUIRE(
"foo" == *opt);
719 const auto& opt_const = opt;
720 REQUIRE(
"foo" == *opt_const);
721 REQUIRE(opt->size() == 3);
722 REQUIRE(opt_const->size() == 3);
724 constexpr optional<ConstexprType> opt1(1);
725 static_assert(opt1->x == 1,
"");
731 #if defined(__GNUC__) && !defined(__clang__) 732 #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 9) 733 #define SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG 739 using O = optional<std::string>;
740 using CO =
const optional<std::string>;
741 O lvalue(in_place,
"lvalue");
742 CO clvalue(in_place,
"clvalue");
743 REQUIRE(
"lvalue" == lvalue.value());
744 REQUIRE(
"clvalue" == clvalue.value());
745 REQUIRE(
"xvalue" == O(in_place,
"xvalue").value());
746 #ifndef SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG 747 REQUIRE(
"cxvalue" == CO(in_place,
"cxvalue").value());
748 REQUIRE(
"&" == TypeQuals(lvalue.value()));
749 REQUIRE(
"c&" == TypeQuals(clvalue.value()));
750 REQUIRE(
"&&" == TypeQuals(O(in_place,
"xvalue").value()));
751 REQUIRE(
"c&&" == TypeQuals(CO(in_place,
"cxvalue").value()));
755 SECTION(
"DerefOperator")
757 using O = optional<std::string>;
758 using CO =
const optional<std::string>;
759 O lvalue(in_place,
"lvalue");
760 CO clvalue(in_place,
"clvalue");
761 REQUIRE(
"lvalue" == *lvalue);
762 REQUIRE(
"clvalue" == *clvalue);
763 REQUIRE(
"xvalue" == *O(in_place,
"xvalue"));
764 #ifndef SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG 765 REQUIRE(
"cxvalue" == *CO(in_place,
"cxvalue"));
766 REQUIRE(
"&" == TypeQuals(*lvalue));
767 REQUIRE(
"c&" == TypeQuals(*clvalue));
768 REQUIRE(
"&&" == TypeQuals(*O(in_place,
"xvalue")));
769 REQUIRE(
"c&&" == TypeQuals(*CO(in_place,
"cxvalue")));
772 constexpr optional<int> opt1(1);
773 static_assert(*opt1 == 1,
"");
775 #if !defined(SKIP_CONSTEXPR_TEST_DUE_TO_CLANG_BUG) && \ 776 !defined(SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG) 777 using COI =
const optional<int>;
778 static_assert(*COI(2) == 2,
"");
784 optional<double> opt_empty, opt_set = 1.2;
785 REQUIRE(42.0 == opt_empty.value_or(42));
786 REQUIRE(1.2 == opt_set.value_or(42));
787 REQUIRE(42.0 == optional<double>().value_or(42));
788 REQUIRE(1.2 == optional<double>(1.2).value_or(42));
790 #ifndef SKIP_CONSTEXPR_TEST_DUE_TO_CLANG_BUG 791 constexpr optional<double> copt_empty;
792 static_assert(42.0 == copt_empty.value_or(42),
"");
794 constexpr optional<double> copt_set = {1.2};
795 static_assert(1.2 == copt_set.value_or(42),
"");
797 using COD =
const optional<double>;
798 static_assert(42.0 == COD().value_or(42),
"");
799 static_assert(1.2 == COD(1.2).value_or(42),
"");
804 SECTION(
"make_optional")
806 auto opt_int = make_optional(42);
807 REQUIRE((std::is_same<decltype(opt_int), optional<int>>::value));
808 REQUIRE(42 == opt_int);
810 StructorListener listener;
811 Listenable::listener = &listener;
813 optional<Listenable> opt0 = make_optional<Listenable>();
814 REQUIRE(1 == listener.construct0);
815 optional<Listenable> opt1 = make_optional<Listenable>(1);
816 REQUIRE(1 == listener.construct1);
817 optional<Listenable> opt2 = make_optional<Listenable>(1, 2);
818 REQUIRE(1 == listener.construct2);
819 optional<Listenable> opt3 = make_optional<Listenable>({1});
820 optional<Listenable> opt4 = make_optional<Listenable>({1, 2});
821 REQUIRE(2 == listener.listinit);
824 SECTION(
"Comparisons")
826 optional<int> ae, be, a2 = 2, b2 = 2, a4 = 4, b4 = 4;
828 #define optionalTest_Comparisons_EXPECT_LESS(x, y) \ 829 REQUIRE_FALSE((x) == (y)); \ 830 REQUIRE((x) != (y)); \ 831 REQUIRE((x) < (y)); \ 832 REQUIRE_FALSE((x) > (y)); \ 833 REQUIRE((x) <= (y)); \ 834 REQUIRE_FALSE((x) >= (y)); 836 #define optionalTest_Comparisons_EXPECT_SAME(x, y) \ 837 REQUIRE((x) == (y)); \ 838 REQUIRE_FALSE((x) != (y)); \ 839 REQUIRE_FALSE((x) < (y)); \ 840 REQUIRE_FALSE((x) > (y)); \ 841 REQUIRE((x) <= (y)); \ 844 #define optionalTest_Comparisons_EXPECT_GREATER(x, y) \ 845 REQUIRE_FALSE((x) == (y)); \ 846 REQUIRE((x) != (y)); \ 847 REQUIRE_FALSE((x) < (y)); \ 848 REQUIRE((x) > (y)); \ 849 REQUIRE_FALSE((x) <= (y)); \ 856 optionalTest_Comparisons_EXPECT_SAME(nullopt, be);
857 optionalTest_Comparisons_EXPECT_LESS(nullopt, b2);
859 optionalTest_Comparisons_EXPECT_LESS(nullopt, b4);
861 optionalTest_Comparisons_EXPECT_SAME(ae, nullopt);
862 optionalTest_Comparisons_EXPECT_SAME(ae, be);
863 optionalTest_Comparisons_EXPECT_LESS(ae, b2);
864 optionalTest_Comparisons_EXPECT_LESS(ae, 3);
865 optionalTest_Comparisons_EXPECT_LESS(ae, b4);
867 optionalTest_Comparisons_EXPECT_GREATER(a2, nullopt);
868 optionalTest_Comparisons_EXPECT_GREATER(a2, be);
869 optionalTest_Comparisons_EXPECT_SAME(a2, b2);
870 optionalTest_Comparisons_EXPECT_LESS(a2, 3);
871 optionalTest_Comparisons_EXPECT_LESS(a2, b4);
874 optionalTest_Comparisons_EXPECT_GREATER(3, be);
875 optionalTest_Comparisons_EXPECT_GREATER(3, b2);
876 optionalTest_Comparisons_EXPECT_SAME(3, 3);
877 optionalTest_Comparisons_EXPECT_LESS(3, b4);
879 optionalTest_Comparisons_EXPECT_GREATER(a4, nullopt);
880 optionalTest_Comparisons_EXPECT_GREATER(a4, be);
881 optionalTest_Comparisons_EXPECT_GREATER(a4, b2);
882 optionalTest_Comparisons_EXPECT_GREATER(a4, 3);
883 optionalTest_Comparisons_EXPECT_SAME(a4, b4);
886 SECTION(
"SwapRegression")
888 StructorListener listener;
889 Listenable::listener = &listener;
892 optional<Listenable> a;
893 optional<Listenable> b(in_place);
897 REQUIRE(1 == listener.construct0);
898 REQUIRE(1 == listener.move);
899 REQUIRE(2 == listener.destruct);
902 optional<Listenable> a(in_place);
903 optional<Listenable> b;
907 REQUIRE(2 == listener.construct0);
908 REQUIRE(2 == listener.move);
909 REQUIRE(4 == listener.destruct);
912 SECTION(
"BigStringLeakCheck")
914 constexpr
size_t n = 1 << 16;
916 using OS = optional<std::string>;
920 OS c = std::string(n,
'c');
921 std::string sd(n,
'd');
923 OS e(in_place, n,
'e');
935 OS oc = std::string(n,
'c');
936 std::string sod(n,
'd');
938 OS oe(in_place, n,
'e');
942 OS ma(std::move(oa));
943 OS mb(std::move(ob));
944 OS mc(std::move(oc));
945 OS md(std::move(od));
946 OS me(std::move(oe));
947 OS mf(std::move(of));
951 OS ac1 = std::string(n,
'c');
952 std::string sad1(n,
'd');
954 OS ae1(in_place, n,
'e');
960 OS ac2 = std::string(n,
'c');
961 std::string sad2(n,
'd');
963 OS ae2(in_place, n,
'e');
976 OS ac3 = std::string(n,
'c');
977 std::string sad3(n,
'd');
979 OS ae3(in_place, n,
'e');
992 OS ac4 = std::string(n,
'c');
993 std::string sad4(n,
'd');
995 OS ae4(in_place, n,
'e');
999 aa4 = OS(in_place, n,
'a');
1000 ab4 = OS(in_place, n,
'b');
1001 ac4 = OS(in_place, n,
'c');
1002 ad4 = OS(in_place, n,
'd');
1003 ae4 = OS(in_place, n,
'e');
1004 af4 = OS(in_place, n,
'f');
1008 OS ac5 = std::string(n,
'c');
1009 std::string sad5(n,
'd');
1011 OS ae5(in_place, n,
'e');
1013 af5.emplace(n,
'f');
1015 std::string saa5(n,
'a');
1016 std::string sab5(n,
'a');
1017 std::string sac5(n,
'a');
1018 std::string sad52(n,
'a');
1019 std::string sae5(n,
'a');
1020 std::string saf5(n,
'a');
1031 OS ac6 = std::string(n,
'c');
1032 std::string sad6(n,
'd');
1034 OS ae6(in_place, n,
'e');
1036 af6.emplace(n,
'f');
1038 aa6 = std::string(n,
'a');
1039 ab6 = std::string(n,
'b');
1040 ac6 = std::string(n,
'c');
1041 ad6 = std::string(n,
'd');
1042 ae6 = std::string(n,
'e');
1043 af6 = std::string(n,
'f');
1047 OS ac7 = std::string(n,
'c');
1048 std::string sad7(n,
'd');
1050 OS ae7(in_place, n,
'e');
1052 af7.emplace(n,
'f');
1054 aa7.emplace(n,
'A');
1055 ab7.emplace(n,
'B');
1056 ac7.emplace(n,
'C');
1057 ad7.emplace(n,
'D');
1058 ae7.emplace(n,
'E');
1059 af7.emplace(n,
'F');
1062 SECTION(
"MoveAssignRegression")
1064 StructorListener listener;
1065 Listenable::listener = &listener;
1068 optional<Listenable> a;
1073 REQUIRE(1 == listener.construct0);
1074 REQUIRE(1 == listener.move);
1075 REQUIRE(2 == listener.destruct);
1078 SECTION(
"ValueType")
1080 REQUIRE((std::is_same<optional<int>::value_type,
int>::value));
1081 REQUIRE((std::is_same<optional<std::string>::value_type, std::string>::value));
1082 REQUIRE_FALSE((std::is_same<optional<int>::value_type, nullopt_t>::value));
1087 std::hash<optional<int>> hash;
1088 std::set<size_t> hashcodes;
1089 hashcodes.insert(hash(nullopt));
1090 for (
int i = 0; i < 100; ++i) {
1091 hashcodes.insert(hash(i));
1093 REQUIRE(hashcodes.size() > 90);
1096 struct MoveMeNoThrow {
1097 MoveMeNoThrow() : x(0) {}
1098 MoveMeNoThrow(
const MoveMeNoThrow& other) : x(other.x) {
1099 LOG(fatal) <<
"Should not be called.";
1101 MoveMeNoThrow(MoveMeNoThrow&& other) noexcept : x(other.x) {}
1105 struct MoveMeThrow {
1106 MoveMeThrow() : x(0) {}
1107 MoveMeThrow(
const MoveMeThrow& other) : x(other.x) {}
1108 MoveMeThrow(MoveMeThrow&& other) : x(other.x) {}
1115 std::is_nothrow_move_constructible<optional<MoveMeNoThrow>>::value,
"");
1117 !std::is_nothrow_move_constructible<optional<MoveMeThrow>>::value,
"");
1118 std::vector<optional<MoveMeNoThrow>> v;
1119 for (
int i = 0; i < 10; ++i)