实现一个 std::optional
如果写过 c#
或者是 rust
,那么对于里面的可空类型一定是很常用的。在 c++17 中添加了 std::optional
,也就是所谓的可空类型。
不过这里的实现是 placement new 的方式,也是位于栈上。
struct NoneOption {
NoneOption() = default;
} None;
template <typename Ty> class Option {
private:
using DataByte = std::array<std::uint8_t, sizeof(Ty)>;
public:
constexpr Option() noexcept : has_value_{false} {}
constexpr Option(NoneOption) noexcept : Option() {}
constexpr Option(const Ty &init) : has_value_{true} {
this->ConstructData(init);
}
constexpr Option(Ty &&init) : has_value_{true} {
this->ConstructData(std::move(init));
}
constexpr Option(const Option &other) : has_value_{other.has_value_} {
if (other.has_value_)
this->ConstructData(*other);
}
constexpr Option(Option &&other) noexcept
: data_(std::move(other.data_)), has_value_{std::move(other.has_value_)} {
other.has_value_ = false;
}
constexpr auto operator=(const Option &other) -> Option & {
this->Reset();
if (other.has_value_)
this->ConstructData(*other);
this->has_value_ = other.has_value_;
}
constexpr auto operator=(Option &&other) noexcept {
this->Reset();
this->data_ = std::move(other.data_);
this->has_value_ = other.has_value_;
other.has_value_ = false;
}
constexpr ~Option() noexcept {
this->ReinterpretCastData()->~Ty();
this->has_value_ = false;
}
public:
constexpr auto HasValue() const noexcept -> bool { return this->has_value_; }
constexpr explicit operator bool() const noexcept { return this->HasValue(); }
public:
constexpr auto operator->() const noexcept -> const Ty * {
return this->ReinterpretCastData();
}
constexpr auto operator->() noexcept -> Ty * {
return this->ReinterpretCastData();
}
constexpr auto operator*() const & noexcept -> const Ty & {
return *this->ReinterpretCastData();
}
constexpr auto operator*() & noexcept -> Ty & {
return *this->ReinterpretCastData();
}
constexpr auto operator*() const && noexcept -> const Ty && {
return std::move(*this->ReinterpretCastData());
}
constexpr auto operator*() && noexcept -> Ty && {
return std::move(*this->ReinterpretCastData());
}
public:
template <typename... Args> constexpr auto Emplace(Args &&...args) -> void {
if (this->has_value_) {
this->Reset();
}
this->ConstructData(std::forward<Args>(args)...);
}
constexpr auto Reset() noexcept -> void {
if (this->has_value_) {
this->ReinterpretCastData()->~Ty();
}
}
constexpr auto Swap(Option &other) noexcept -> void {
std::swap(this->data_, other.data_);
std::swap(this->has_value_, other.has_value_);
}
constexpr auto Value() const & -> const Ty & {
if (this->has_value_) {
return **this;
}
throw std::exception();
}
constexpr auto Value() const && -> const Ty && {
if (this->has_value_) {
return std::move(**this);
}
throw std::exception();
}
template <typename U>
constexpr auto ValueOr(U &&default_value) const & -> Ty {
if (this->has_value_) {
return **this;
}
return static_cast<Ty>(default_value);
}
template <typename U> constexpr auto ValueOr(U &&default_value) && -> Ty {
if (this->has_value_) {
return std::move(**this);
}
return static_cast<Ty>(default_value);
}
private:
template <typename... Args>
constexpr auto ConstructData(Args &&...args) -> void {
new (this->data_.data()) Ty(std::forward<Args>(args)...);
}
constexpr auto ReinterpretCastData() noexcept -> Ty * {
return reinterpret_cast<Ty *>(this->data_.data());
}
constexpr auto ReinterpretCastData() const noexcept -> const Ty * {
return reinterpret_cast<const Ty *>(this->data_.data());
}
private:
DataByte data_;
bool has_value_;
};
标签:std,const,实现,auto,value,constexpr,other,optional
From: https://www.cnblogs.com/FlandreScarlet/p/18064986