Skip to content

Commit b0e8f1e

Browse files
committed
common: fix assignment operator of optional_t for non-trivial types
1 parent 0cef054 commit b0e8f1e

1 file changed

Lines changed: 8 additions & 4 deletions

File tree

src/common/optional.hpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class optional_t {
5656
static_assert(!std::is_const<T>::value, "");
5757
static_assert(!std::is_volatile<T>::value, "");
5858

59-
optional_t(const nullopt_t nullopt_) : has_value_(false), dummy {} {}
59+
optional_t(const nullopt_t) : has_value_(false), dummy {} {}
6060
optional_t() : optional_t(nullopt) {}
6161
optional_t(const T &object) : has_value_(true), value_(object) {}
6262
optional_t(const optional_t &other)
@@ -71,22 +71,26 @@ class optional_t {
7171
if (has_value_) value_.~T();
7272
}
7373

74-
optional_t &operator=(const nullopt_t nullopt_) {
74+
optional_t &operator=(const nullopt_t) {
7575
if (has_value_) value_.~T();
7676
has_value_ = false;
77+
return *this;
7778
}
7879
optional_t &operator=(const optional_t &other) {
7980
if (this == &other) return *this;
8081
if (has_value_) value_.~T();
8182
has_value_ = other.has_value_;
82-
if (has_value_) value_ = other.value_;
83+
// Placement-new construct: value_ is not a living object here (either
84+
// it was just destroyed above or it was never constructed), so we must
85+
// construct it rather than assign to it.
86+
if (has_value_) new (std::addressof(value_)) T(other.value_);
8387
return *this;
8488
}
8589
optional_t &operator=(optional_t &&other) {
8690
if (this == &other) return *this;
8791
if (has_value_) value_.~T();
8892
has_value_ = other.has_value_;
89-
if (has_value_) value_ = std::move(other.value_);
93+
if (has_value_) new (std::addressof(value_)) T(std::move(other.value_));
9094
return *this;
9195
}
9296

0 commit comments

Comments
 (0)