实现一个 std::optional
实现一个 std::optional
如果写过 c#
或者是 rust
,那么对于里面的可空类型一定是很常用的。在 c++17 中添加了 std::optional
,也就是所谓的可空类型。
不过这里的实现是 placement new 的方式,也是位于栈上。
实现的主要点是申请一块内存空间,由于需要效率,因此这块内存空间的生命周期应当与对象一致,所以这边使用了 std::array
作为代替。
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> requires requires(Args... args) { new Ty(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_; };
本文作者:フランドール·スカーレット
本文链接:https://www.cnblogs.com/FlandreScarlet/p/18064986
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步