Skip to content

Commit

Permalink
Merge pull request #8 from steve-downey/assignment-constexp
Browse files Browse the repository at this point in the history
Make assignment operators constexpr
  • Loading branch information
steve-downey authored Jul 21, 2024
2 parents f00fe6d + 01a0815 commit bc1bab9
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 8 deletions.
16 changes: 8 additions & 8 deletions include/Beman/Optional26/optional.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ class optional {
value_.~T();
}

~optional()
constexpr ~optional()
requires std::is_trivially_destructible_v<T>
= default;

Expand Down Expand Up @@ -426,7 +426,7 @@ class optional {
}
}

optional& operator=(const optional& rhs)
constexpr optional& operator=(const optional& rhs)
requires std::is_copy_constructible_v<T> && std::is_copy_assignable_v<T> &&
(!std::is_trivially_copy_assignable_v<T>)
{
Expand All @@ -435,11 +435,11 @@ class optional {
else if (has_value())
value_ = rhs.value_;
else
std::construct_at(std::addressof(&value_), rhs.value_);
std::construct_at(std::addressof(value_), rhs.value_);
return *this;
}

optional& operator=(const optional&)
constexpr optional& operator=(const optional&)
requires std::is_copy_constructible_v<T> && std::is_copy_assignable_v<T> &&
std::is_trivially_copy_constructible_v<T> && std::is_trivially_copy_assignable_v<T>
= default;
Expand All @@ -457,7 +457,7 @@ class optional {
return *this;
}

optional& operator=(optional&&)
constexpr optional& operator=(optional&&)
requires std::is_move_constructible_v<T> && std::is_move_assignable_v<T> &&
std::is_trivially_move_constructible_v<T> && std::is_trivially_move_assignable_v<T>
= default;
Expand Down Expand Up @@ -584,7 +584,7 @@ class optional {
/// Assigns the stored value from `u`, destroying the old value if there
/// was one.
template <class U = T>
optional& operator=(U&& u)
constexpr optional& operator=(U&& u)
requires enable_assign_forward<T, U>
{
if (has_value()) {
Expand All @@ -601,7 +601,7 @@ class optional {
/// Copies the value from `rhs` if there is one. Otherwise resets the
/// stored value in `*this`.
template <class U>
optional& operator=(const optional<U>& rhs)
constexpr optional& operator=(const optional<U>& rhs)
requires enable_assign_from_other<T, U, const U&>
{
if (has_value()) {
Expand All @@ -624,7 +624,7 @@ class optional {
/// Moves the value from `rhs` if there is one. Otherwise resets the stored
/// value in `*this`.
template <class U>
optional& operator=(optional<U>&& rhs)
constexpr optional& operator=(optional<U>&& rhs)
requires enable_assign_from_other<T, U, U>
{
if (has_value()) {
Expand Down
26 changes: 26 additions & 0 deletions src/Beman/Optional26/tests/optional.t.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,31 @@ TEST(OptionalTest, AssignmentValue) {

o1 = std::move(o4);
EXPECT_TRUE(*o1 == 42);

/*
template <class U = T>
constexpr optional& operator=(U&& u)
*/
short s = 54;
o1 = s;
EXPECT_TRUE(*o1 == 54);

struct not_trivial_copy_assignable {
int i_;
not_trivial_copy_assignable& operator=(const not_trivial_copy_assignable&);
};


/*
optional& operator=(const optional& rhs)
requires std::is_copy_constructible_v<T> && std::is_copy_assignable_v<T> &&
(!std::is_trivially_copy_assignable_v<T>)
*/
beman::optional26::optional<not_trivial_copy_assignable> o5{5};
beman::optional26::optional<not_trivial_copy_assignable> o6;
o6 = o5;
EXPECT_TRUE(o5->i_ == 5);

}

TEST(OptionalTest, Triviality) {
Expand Down Expand Up @@ -648,6 +673,7 @@ TEST(ViewMaybeTest, BreathingTest) {
ASSERT_EQ(*std::begin(m), 1);

m = {};
ASSERT_FALSE(m);
// ASSERT_TRUE(m.size() == 0);
// ASSERT_TRUE(m1.size() == 1);

Expand Down
79 changes: 79 additions & 0 deletions src/Beman/Optional26/tests/optional_constexpr.t.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1663,3 +1663,82 @@ consteval bool testEmplaceInitList() {
(std::get<1>(o->t) == 3);
}
static_assert(testEmplaceInitList());

consteval bool testAssignment() {
beman::optional26::optional<int> o1 = 42;
beman::optional26::optional<int> o2 = 12;
beman::optional26::optional<int> o3;

bool retval = true;

o1 = std::move(o1);
retval &= (*o1 == 42);

o1 = {};

return retval;
}
static_assert(testAssignment());

consteval bool testAssignmentValue() {
beman::optional26::optional<int> o1 = 42;
beman::optional26::optional<int> o2 = 12;
beman::optional26::optional<int> o3;

bool retval = true;

o1 = o1;
retval &= (*o1 == 42);

o1 = o2;
retval &= (*o1 == 12);

o1 = o3;
retval &= (!o1);

o1 = 42;
retval &= (*o1 == 42);

o1 = beman::optional26::nullopt;
retval &= (!o1);

o1 = std::move(o2);
retval &= (*o1 == 12);

beman::optional26::optional<short> o4 = 42;

o1 = o4;
retval &= (*o1 == 42);

o1 = std::move(o4);
retval &= (*o1 == 42);

/*
template <class U = T>
constexpr optional& operator=(U&& u)
*/

short s = 54;
o1 = s;
retval &= (*o1 == 54);

struct not_trivial_copy_assignable {
int i_;
not_trivial_copy_assignable& operator=(const not_trivial_copy_assignable&);
};

/*
optional& operator=(const optional& rhs)
requires std::is_copy_constructible_v<T> && std::is_copy_assignable_v<T> &&
(!std::is_trivially_copy_assignable_v<T>)
*/
beman::optional26::optional<not_trivial_copy_assignable> o5{5};
beman::optional26::optional<not_trivial_copy_assignable> o6;
o6 = o5;
retval &= (o5->i_ == 5);

return retval;

}

static_assert(testAssignmentValue());

0 comments on commit bc1bab9

Please sign in to comment.