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 #ifndef DUNE_FUNCTIONS_COMMON_POLYMORPHICSMALLOBJECT_HH
4 #define DUNE_FUNCTIONS_COMMON_POLYMORPHICSMALLOBJECT_HH
5 
6 #include <cstddef>
7 #include <utility>
8 #include <type_traits>
9 #include <algorithm>
10 
11 namespace Dune {
12 namespace Functions {
13 
14 
45 template<class Base, size_t bufferSize>
47 {
48  // Actual buffer size must be > 0
49  static constexpr std::size_t actualBufferSize = std::max(sizeof(std::byte), bufferSize);
50 
51  // Alignment requirement for the buffer. The `Derived` type must have
52  // an alignment requirement that is a divisor of `bufferAlignment`
53  static constexpr std::size_t bufferAlignment = alignof(std::max_align_t);
54 
55 public:
56 
59  p_(nullptr)
60  {}
61 
68  template<class Derived,
69  std::enable_if_t<std::is_base_of_v<Base, std::remove_cv_t<
70  std::remove_reference_t<Derived>>>, int> = 0>
71  PolymorphicSmallObject(Derived&& derived)
72  {
73  constexpr bool useBuffer = (sizeof(Derived) <= bufferSize)
74  && (bufferAlignment % alignof(Derived) == 0);
75 
76  if constexpr (useBuffer) {
77  p_ = new (&buffer_) Derived(std::forward<Derived>(derived));
78  } else {
79  p_ = new Derived(std::forward<Derived>(derived));
80  }
81  }
82 
85  {
86  moveToWrappedObject(std::move(other));
87  }
88 
91  {
92  copyToWrappedObject(other);
93  }
94 
97  {
98  destroyWrappedObject();
99  }
100 
103  {
104  if (&other!=this)
105  {
106  destroyWrappedObject();
107  copyToWrappedObject(other);
108  }
109  return *this;
110  }
111 
114  {
115  destroyWrappedObject();
116  moveToWrappedObject(std::move(other));
117  return *this;
118  }
119 
121  explicit operator bool() const
122  {
123  return p_;
124  }
125 
127  bool bufferUsed() const
128  {
129  return ((void*) (p_) == (void*)(&buffer_));
130  }
131 
133  const Base& get() const
134  {
135  return *p_;
136  }
137 
139  Base& get()
140  {
141  return *p_;
142  }
143 
144 private:
145 
146  void destroyWrappedObject() noexcept
147  {
148  if (operator bool())
149  {
150  if (bufferUsed())
151  p_->~Base();
152  else
153  delete p_;
154  }
155  }
156 
157  void moveToWrappedObject(PolymorphicSmallObject&& other) noexcept
158  {
159  if (other.bufferUsed())
160  p_ = other.p_->move(&buffer_);
161  else
162  {
163  // We don't need to check for &other_!=this, because you can't
164  // have an rvalue to *this and call it's assignment/constructor
165  // at the same time. (Despite trying to shoot yourself in the foot
166  // with std::move explicitly.)
167 
168  // Take ownership of allocated object
169  p_ = other.p_;
170 
171  // Leave pointer in a clean state to avoid double freeing it.
172  other.p_ = 0;
173  }
174  }
175 
176  void copyToWrappedObject(const PolymorphicSmallObject& other)
177  {
178  if (other.bufferUsed())
179  p_ = other.p_->clone(&buffer_);
180  else
181  p_ = other.p_->clone();
182  }
183 
184  alignas(bufferAlignment) std::byte buffer_[actualBufferSize];
185  Base* p_;
186 };
187 
188 
189 } // namespace Functions
190 } // namespace Dune
191 
192 #endif // DUNE_FUNCTIONS_COMMON_POLYMORPHICSMALLOBJECT_HH
A wrapper providing small object optimization with polymorphic types.
Definition: polymorphicsmallobject.hh:47
PolymorphicSmallObject & operator=(PolymorphicSmallObject &&other) noexcept
Move assignment from other PolymorphicSmallObject.
Definition: polymorphicsmallobject.hh:113
bool bufferUsed() const
Check if object is stored in internal stack buffer.
Definition: polymorphicsmallobject.hh:127
PolymorphicSmallObject(Derived &&derived)
Construct from object.
Definition: polymorphicsmallobject.hh:71
PolymorphicSmallObject(PolymorphicSmallObject &&other) noexcept
Move constructor from other PolymorphicSmallObject.
Definition: polymorphicsmallobject.hh:84
Base & get()
Obtain mutable reference to stored object.
Definition: polymorphicsmallobject.hh:139
PolymorphicSmallObject & operator=(const PolymorphicSmallObject &other)
Copy assignment from other PolymorphicSmallObject.
Definition: polymorphicsmallobject.hh:102
PolymorphicSmallObject(const PolymorphicSmallObject &other)
Copy constructor from other PolymorphicSmallObject.
Definition: polymorphicsmallobject.hh:90
~PolymorphicSmallObject()
Destructor.
Definition: polymorphicsmallobject.hh:96
const Base & get() const
Obtain reference to stored object.
Definition: polymorphicsmallobject.hh:133
PolymorphicSmallObject()
Default constructor.
Definition: polymorphicsmallobject.hh:58
Definition: polynomial.hh:13
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 16, 22:29, 2024)