diff options
author | Noel Grandin <noel.grandin@collabora.co.uk> | 2021-08-16 18:47:58 +0200 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2021-08-18 12:09:09 +0200 |
commit | 62d11b0e072b2f34b9f52c33a73cbb54d8112307 (patch) | |
tree | ea3a12c0db2e1dd61220a24cd60f8d0de59bab2a /include/editeng | |
parent | 483ad8ac7e2374aa17dc83a4bf81fff1cbbcb98d (diff) |
specialise std::optional for OutlineParaObject
we can re-use the o3tl::wrapper pointer to indicate empty
Change-Id: I26e502a7dacfb2bd3d465e71c8fdd89a6a80969b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/120553
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Diffstat (limited to 'include/editeng')
-rw-r--r-- | include/editeng/outlobj.hxx | 90 |
1 files changed, 86 insertions, 4 deletions
diff --git a/include/editeng/outlobj.hxx b/include/editeng/outlobj.hxx index fac9bed9ffb9..8ba1dedb3f16 100644 --- a/include/editeng/outlobj.hxx +++ b/include/editeng/outlobj.hxx @@ -17,8 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_EDITENG_OUTLOBJ_HXX -#define INCLUDED_EDITENG_OUTLOBJ_HXX +#pragma once #include <editeng/paragraphdata.hxx> #include <editeng/editengdllapi.h> @@ -26,6 +25,7 @@ #include <svl/poolitem.hxx> #include <svl/style.hxx> #include <o3tl/cow_wrapper.hxx> +#include <stdexcept> #include <memory> class EditTextObject; @@ -36,7 +36,7 @@ enum class TextRotation; * This is the guts of OutlinerParaObject, refcounted and shared among * multiple instances of OutlinerParaObject. */ -struct OutlinerParaObjData +struct EDITENG_DLLPUBLIC OutlinerParaObjData { // data members std::unique_ptr<EditTextObject> mpEditTextObject; @@ -64,8 +64,14 @@ struct OutlinerParaObjData class EDITENG_DLLPUBLIC OutlinerParaObject { +friend class std::optional<OutlinerParaObject>; ::o3tl::cow_wrapper< OutlinerParaObjData > mpImpl; + OutlinerParaObject(std::nullopt_t) noexcept + : mpImpl(std::nullopt) {} + OutlinerParaObject( const OutlinerParaObject& other, std::nullopt_t ) noexcept + : mpImpl(other.mpImpl, std::nullopt) {} + public: // constructors/destructor OutlinerParaObject(std::unique_ptr<EditTextObject>, const ParagraphDataVector&, bool bIsEditDoc); @@ -117,6 +123,82 @@ public: void dumpAsXml(xmlTextWriterPtr pWriter) const; }; -#endif +namespace std +{ + /** Specialise std::optional template for the case where we are wrapping a o3tl::cow_wrapper + type, and we can make the pointer inside the cow_wrapper act as an empty value, + and save ourselves some storage */ + template<> + class optional<OutlinerParaObject> + { + public: + optional() noexcept : maParaObject(std::nullopt) {} + optional(std::nullopt_t) noexcept : maParaObject(std::nullopt) {} + optional(const optional& other) : + maParaObject(other.maParaObject, std::nullopt) {} + optional(optional&& other) noexcept : + maParaObject(std::move(other.maParaObject)) {} + optional(OutlinerParaObject&& para) noexcept : + maParaObject(std::move(para)) {} + optional(const OutlinerParaObject& para) noexcept : + maParaObject(para) {} + template< class... Args > + explicit optional( std::in_place_t, Args&&... args ) : + maParaObject(std::forward<Args>(args)...) {} + + optional& operator=(optional const & other) + { + maParaObject = other.maParaObject; + return *this; + } + optional& operator=(optional&& other) noexcept + { + maParaObject = std::move(other.maParaObject); + return *this; + } + template< class... Args > + void emplace(Args&&... args ) + { + maParaObject = OutlinerParaObject(std::forward<Args>(args)...); + } + + bool has_value() const noexcept { return !maParaObject.mpImpl.empty(); } + explicit operator bool() const noexcept { return !maParaObject.mpImpl.empty(); } + void reset() { maParaObject.mpImpl.set_empty(); } + + OutlinerParaObject& value() + { + throwIfEmpty(); + return maParaObject; + } + OutlinerParaObject& operator*() + { + throwIfEmpty(); + return maParaObject; + } + const OutlinerParaObject& operator*() const + { + throwIfEmpty(); + return maParaObject; + } + OutlinerParaObject* operator->() + { + throwIfEmpty(); + return &maParaObject; + } + const OutlinerParaObject* operator->() const + { + throwIfEmpty(); + return &maParaObject; + } + private: + void throwIfEmpty() const + { + if (maParaObject.mpImpl.empty()) + throw std::logic_error("empty std::optional<OutlinerParaObject>"); + } + OutlinerParaObject maParaObject; + }; +}; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |