dune-functions 2.9.0
polymorphicsmallobject.hh
Go to the documentation of this file.
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3#ifndef DUNE_FUNCTIONS_COMMON_POLYMORPHICSMALLOBJECT_HH
4#define DUNE_FUNCTIONS_COMMON_POLYMORPHICSMALLOBJECT_HH
5
6#include <utility>
7#include <type_traits>
8
9namespace Dune {
10namespace Functions {
11
12
43template<class Base, size_t bufferSize>
45{
46public:
47
50 p_(nullptr)
51 {}
52
59 template<class Derived,
60 typename std::enable_if<std::is_base_of<Base, std::remove_cv_t<
61 std::remove_reference_t<Derived>>>::value, int>::type = 0>
62 PolymorphicSmallObject(Derived&& derived)
63 {
64 constexpr bool useBuffer = sizeof(Derived) <= bufferSize;
65 if constexpr (useBuffer) {
66 p_ = new (&buffer_) Derived(std::forward<Derived>(derived));
67 } else {
68 p_ = new Derived(std::forward<Derived>(derived));
69 }
70 }
71
74 {
75 moveToWrappedObject(std::move(other));
76 }
77
80 {
81 copyToWrappedObject(other);
82 }
83
86 {
87 destroyWrappedObject();
88 }
89
92 {
93 if (&other!=this)
94 {
95 destroyWrappedObject();
96 copyToWrappedObject(other);
97 }
98 return *this;
99 }
100
103 {
104 destroyWrappedObject();
105 moveToWrappedObject(std::move(other));
106 return *this;
107 }
108
110 explicit operator bool() const
111 {
112 return p_;
113 }
114
116 bool bufferUsed() const
117 {
118 return ((void*) (p_) == (void*)(&buffer_));
119 }
120
122 const Base& get() const
123 {
124 return *p_;
125 }
126
128 Base& get()
129 {
130 return *p_;
131 }
132
133private:
134
135 void destroyWrappedObject() noexcept
136 {
137 if (operator bool())
138 {
139 if (bufferUsed())
140 p_->~Base();
141 else
142 delete p_;
143 }
144 }
145
146 void moveToWrappedObject(PolymorphicSmallObject&& other) noexcept
147 {
148 if (other.bufferUsed())
149 p_ = other.p_->move(&buffer_);
150 else
151 {
152 // We don't need to check for &other_!=this, because you can't
153 // have an rvalue to *this and call it's assignment/constructor
154 // at the same time. (Despite trying to shoot yourself in the foot
155 // with std::move explicitly.)
156
157 // Take ownership of allocated object
158 p_ = other.p_;
159
160 // Leave pointer in a clean state to avoid double freeing it.
161 other.p_ = 0;
162 }
163 }
164
165 void copyToWrappedObject(const PolymorphicSmallObject& other)
166 {
167 if (other.bufferUsed())
168 p_ = other.p_->clone(&buffer_);
169 else
170 p_ = other.p_->clone();
171 }
172
173 std::aligned_storage_t<bufferSize> buffer_;
174 Base* p_;
175};
176
177
178} // namespace Functions
179} // namespace Dune
180
181#endif // DUNE_FUNCTIONS_COMMON_POLYMORPHICSMALLOBJECT_HH
Definition: polynomial.hh:10
A wrapper providing small object optimization with polymorphic types.
Definition: polymorphicsmallobject.hh:45
const Base & get() const
Obtain reference to stored object.
Definition: polymorphicsmallobject.hh:122
bool bufferUsed() const
Check if object is stored in internal stack buffer.
Definition: polymorphicsmallobject.hh:116
PolymorphicSmallObject(Derived &&derived)
Construct from object.
Definition: polymorphicsmallobject.hh:62
PolymorphicSmallObject(PolymorphicSmallObject &&other) noexcept
Move constructor from other PolymorphicSmallObject.
Definition: polymorphicsmallobject.hh:73
PolymorphicSmallObject & operator=(const PolymorphicSmallObject &other)
Copy assignment from other PolymorphicSmallObject.
Definition: polymorphicsmallobject.hh:91
PolymorphicSmallObject & operator=(PolymorphicSmallObject &&other) noexcept
Move assignment from other PolymorphicSmallObject.
Definition: polymorphicsmallobject.hh:102
PolymorphicSmallObject(const PolymorphicSmallObject &other)
Copy constructor from other PolymorphicSmallObject.
Definition: polymorphicsmallobject.hh:79
~PolymorphicSmallObject()
Destructor.
Definition: polymorphicsmallobject.hh:85
PolymorphicSmallObject()
Default constructor.
Definition: polymorphicsmallobject.hh:49
Base & get()
Obtain mutable reference to stored object.
Definition: polymorphicsmallobject.hh:128