diff options
author | koe <ukoe@protonmail.com> | 2023-02-12 13:00:53 -0600 |
---|---|---|
committer | koe <ukoe@protonmail.com> | 2023-02-12 13:00:53 -0600 |
commit | 2a7435e026b114d92809959ca51f96c05572cc07 (patch) | |
tree | a8c2bb2360e4288a4fcc6ee04036799d534e6dcb /src/common | |
parent | add variant class with cleaner interface than boost::variant<> (diff) | |
download | monero-2a7435e026b114d92809959ca51f96c05572cc07.tar.xz |
variant: add mutable unwrap and visitation
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/variant.h | 25 |
1 files changed, 18 insertions, 7 deletions
diff --git a/src/common/variant.h b/src/common/variant.h index a2121c75e..ffb34e40a 100644 --- a/src/common/variant.h +++ b/src/common/variant.h @@ -62,7 +62,6 @@ namespace tools //// // variant: convenience wrapper around boost::variant with a cleaner interface -// - the value may be assigned to but is otherwise read-only // - the variant is 'optional' - an empty variant will evaluate to 'false' and an initialized variant will be 'true' /// template <typename ResultT> @@ -70,6 +69,7 @@ struct variant_static_visitor : public boost::static_visitor<ResultT> { /// provide visitation for empty variants /// - add this to your visitor with: using variant_static_visitor::operator(); + [[noreturn]] ResultT operator()(const boost::blank) { variant_static_visitor_blank_err(); } [[noreturn]] ResultT operator()(const boost::blank) const { variant_static_visitor_blank_err(); } }; @@ -107,14 +107,20 @@ public: template <typename T> bool is_type() const noexcept { return this->index() == this->type_index_of<T>(); } - /// try to get a read-only handle to the embedded value (return nullptr on failure) + /// try to get a handle to the embedded value (return nullptr on failure) template <typename T> - const T* try_unwrap() const + T* try_unwrap() noexcept { return boost::strict_get< T>(&m_value); } + template <typename T> + const T* try_unwrap() const noexcept { return boost::strict_get<const T>(&m_value); } + + /// get a handle to the embedded value + template <typename T> + T& unwrap() { - return boost::strict_get<T>(&m_value); + T *value_ptr{this->try_unwrap<T>()}; + if (!value_ptr) variant_unwrap_err(); + return *value_ptr; } - - /// get a read-only handle to the embedded value template <typename T> const T& unwrap() const { @@ -131,7 +137,7 @@ public: static constexpr int type_index_of() noexcept { using types = boost::mpl::vector<boost::blank, Types...>; - using elem = typename boost::mpl::find<types, T>::type; + using elem = typename boost::mpl::find<types, T>::type; using begin = typename boost::mpl::begin<types>::type; return boost::mpl::distance<begin, elem>::value; } @@ -142,6 +148,11 @@ public: /// apply a visitor to the variant template <typename VisitorT> + typename VisitorT::result_type visit(VisitorT &&visitor) + { + return boost::apply_visitor(std::forward<VisitorT>(visitor), m_value); + } + template <typename VisitorT> typename VisitorT::result_type visit(VisitorT &&visitor) const { return boost::apply_visitor(std::forward<VisitorT>(visitor), m_value); |