Skip to content

Commit 58600ee

Browse files
committed
Fix construction from empty optional<U>
Fixes bemanproject#49 for the constructor case. Adds failing tests, and fixes them.
1 parent 39ed045 commit 58600ee

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

include/Beman/Optional26/optional.hpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1044,7 +1044,13 @@ class optional<T&> {
10441044
}
10451045

10461046
template <class U>
1047-
constexpr explicit(!std::is_convertible_v<U, T>) optional(const optional<U>& rhs) noexcept : optional(*rhs) {}
1047+
constexpr explicit(!std::is_convertible_v<U, T>) optional(const optional<U>& rhs) noexcept {
1048+
static_assert(std::is_constructible_v<std::add_lvalue_reference_t<T>, U>, "Must be able to bind U to T&");
1049+
if (rhs.has_value())
1050+
value_ = std::to_address(rhs);
1051+
else
1052+
value_ = nullptr;
1053+
}
10481054

10491055
// \rSec3[optional.dtor]{Destructor}
10501056

src/Beman/Optional26/tests/optional_ref.t.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,3 +620,39 @@ TEST(OptionalRefTest, AssignFromOptional) {
620620
// EXPECT_EQ(*optional_base_ref, derived(3,4));
621621

622622
}
623+
624+
TEST(OptionalRefTest, ConstructFromOptional) {
625+
int var = 42;
626+
beman::optional26::optional<int&> o1 = beman::optional26::nullopt;
627+
beman::optional26::optional<int&> o2{var};
628+
629+
630+
using beman::optional26::tests::base;
631+
using beman::optional26::tests::derived;
632+
633+
base b{1};
634+
derived d(1, 2);
635+
beman::optional26::optional<base&> empty_base;
636+
beman::optional26::optional<base&> engaged_base{b};
637+
638+
beman::optional26::optional<derived&> empty_derived_ref;
639+
beman::optional26::optional<derived&> engaged_derived_ref{d};
640+
641+
beman::optional26::optional<base&> optional_base_ref{empty_derived_ref};
642+
EXPECT_FALSE(optional_base_ref.has_value());
643+
644+
beman::optional26::optional<base&> optional_base_ref2{engaged_derived_ref};
645+
EXPECT_TRUE(optional_base_ref2.has_value());
646+
647+
beman::optional26::optional<derived> empty_derived;
648+
beman::optional26::optional<derived> engaged_derived{d};
649+
650+
static_assert(std::is_constructible_v<const base&, derived>);
651+
652+
beman::optional26::optional<const base&> optional_base_const_ref{empty_derived};
653+
EXPECT_FALSE(optional_base_const_ref.has_value());
654+
655+
beman::optional26::optional<const base&> optional_base_const_ref2{engaged_derived};
656+
EXPECT_TRUE(optional_base_const_ref2.has_value());
657+
658+
}

0 commit comments

Comments
 (0)