DUNE-FUNCTIONS (unstable)

polymorphicsmallobject.hh
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3
4// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file AUTHORS.md
5// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later
6
7#ifndef DUNE_FUNCTIONS_COMMON_POLYMORPHICSMALLOBJECT_HH
8#define DUNE_FUNCTIONS_COMMON_POLYMORPHICSMALLOBJECT_HH
9
10#include <cstddef>
11#include <utility>
12#include <type_traits>
13#include <algorithm>
14
15namespace Dune {
16namespace Functions {
17
18
49template<class Base, size_t bufferSize>
51{
52 // Actual buffer size must be > 0
53 static constexpr std::size_t actualBufferSize = std::max(sizeof(std::byte), bufferSize);
54
55 // Alignment requirement for the buffer. The `Derived` type must have
56 // an alignment requirement that is a divisor of `bufferAlignment`
57 static constexpr std::size_t bufferAlignment = alignof(std::max_align_t);
58
59public:
60
63 p_(nullptr)
64 {}
65
72 template<class Derived,
73 std::enable_if_t<std::is_base_of_v<Base, std::remove_cv_t<
74 std::remove_reference_t<Derived>>>, int> = 0>
75 PolymorphicSmallObject(Derived&& derived)
76 {
77 constexpr bool useBuffer = (sizeof(Derived) <= bufferSize)
78 && (bufferAlignment % alignof(Derived) == 0);
79
80 if constexpr (useBuffer) {
81 p_ = new (&buffer_) Derived(std::forward<Derived>(derived));
82 } else {
83 p_ = new Derived(std::forward<Derived>(derived));
84 }
85 }
86
89 {
90 moveToWrappedObject(std::move(other));
91 }
92
95 {
96 copyToWrappedObject(other);
97 }
98
101 {
102 destroyWrappedObject();
103 }
104
107 {
108 if (&other!=this)
109 {
110 destroyWrappedObject();
111 copyToWrappedObject(other);
112 }
113 return *this;
114 }
115
118 {
119 destroyWrappedObject();
120 moveToWrappedObject(std::move(other));
121 return *this;
122 }
123
125 explicit operator bool() const
126 {
127 return p_;
128 }
129
131 bool bufferUsed() const
132 {
133 return ((void*) (p_) == (void*)(&buffer_));
134 }
135
137 const Base& get() const
138 {
139 return *p_;
140 }
141
143 Base& get()
144 {
145 return *p_;
146 }
147
148private:
149
150 void destroyWrappedObject() noexcept
151 {
152 if (operator bool())
153 {
154 if (bufferUsed())
155 p_->~Base();
156 else
157 delete p_;
158 }
159 }
160
161 void moveToWrappedObject(PolymorphicSmallObject&& other) noexcept
162 {
163 if (other.bufferUsed())
164 p_ = other.p_->move(&buffer_);
165 else
166 {
167 // We don't need to check for &other_!=this, because you can't
168 // have an rvalue to *this and call it's assignment/constructor
169 // at the same time. (Despite trying to shoot yourself in the foot
170 // with std::move explicitly.)
171
172 // Take ownership of allocated object
173 p_ = other.p_;
174
175 // Leave pointer in a clean state to avoid double freeing it.
176 other.p_ = 0;
177 }
178 }
179
180 void copyToWrappedObject(const PolymorphicSmallObject& other)
181 {
182 if (other.bufferUsed())
183 p_ = other.p_->clone(&buffer_);
184 else
185 p_ = other.p_->clone();
186 }
187
188 alignas(bufferAlignment) std::byte buffer_[actualBufferSize];
189 Base* p_;
190};
191
192
193} // namespace Functions
194} // namespace Dune
195
196#endif // DUNE_FUNCTIONS_COMMON_POLYMORPHICSMALLOBJECT_HH
A wrapper providing small object optimization with polymorphic types.
Definition: polymorphicsmallobject.hh:51
const Base & get() const
Obtain reference to stored object.
Definition: polymorphicsmallobject.hh:137
bool bufferUsed() const
Check if object is stored in internal stack buffer.
Definition: polymorphicsmallobject.hh:131
PolymorphicSmallObject(Derived &&derived)
Construct from object.
Definition: polymorphicsmallobject.hh:75
PolymorphicSmallObject(PolymorphicSmallObject &&other) noexcept
Move constructor from other PolymorphicSmallObject.
Definition: polymorphicsmallobject.hh:88
PolymorphicSmallObject & operator=(const PolymorphicSmallObject &other)
Copy assignment from other PolymorphicSmallObject.
Definition: polymorphicsmallobject.hh:106
PolymorphicSmallObject & operator=(PolymorphicSmallObject &&other) noexcept
Move assignment from other PolymorphicSmallObject.
Definition: polymorphicsmallobject.hh:117
PolymorphicSmallObject(const PolymorphicSmallObject &other)
Copy constructor from other PolymorphicSmallObject.
Definition: polymorphicsmallobject.hh:94
~PolymorphicSmallObject()
Destructor.
Definition: polymorphicsmallobject.hh:100
PolymorphicSmallObject()
Default constructor.
Definition: polymorphicsmallobject.hh:62
Base & get()
Obtain mutable reference to stored object.
Definition: polymorphicsmallobject.hh:143
Definition: polynomial.hh:17
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Aug 13, 22:30, 2024)