dune-functions  2.7.1
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 
9 #include <dune/common/std/type_traits.hh>
10 #include <dune/common/hybridutilities.hh>
11 
12 namespace Dune {
13 namespace Functions {
14 
15 
46 template<class Base, size_t bufferSize>
48 {
49 public:
50 
53  p_(nullptr)
54  {}
55 
62  template<class Derived,
63  typename std::enable_if<std::is_base_of<Base, std::remove_cv_t<
64  std::remove_reference_t<Derived>>>::value, int>::type = 0>
65  PolymorphicSmallObject(Derived&& derived)
66  {
67  using namespace Dune::Hybrid;
68  auto useBuffer = Dune::Std::bool_constant<(sizeof(Derived) <= bufferSize)>();
69  ifElse(useBuffer, [&](auto id) {
70  p_ = new (&buffer_) Derived(std::forward<Derived>(derived));
71  }, [&](auto id) {
72  p_ = new Derived(std::forward<Derived>(derived));
73  });
74  }
75 
78  {
79  moveToWrappedObject(std::move(other));
80  }
81 
84  {
85  copyToWrappedObject(other);
86  }
87 
90  {
91  destroyWrappedObject();
92  }
93 
96  {
97  if (&other!=this)
98  {
99  destroyWrappedObject();
100  copyToWrappedObject(other);
101  }
102  return *this;
103  }
104 
107  {
108  destroyWrappedObject();
109  moveToWrappedObject(std::move(other));
110  return *this;
111  }
112 
114  explicit operator bool() const
115  {
116  return p_;
117  }
118 
120  bool bufferUsed() const
121  {
122  return ((void*) (p_) == (void*)(&buffer_));
123  }
124 
126  const Base& get() const
127  {
128  return *p_;
129  }
130 
132  Base& get()
133  {
134  return *p_;
135  }
136 
137 private:
138 
139  void destroyWrappedObject()
140  {
141  if (operator bool())
142  {
143  if (bufferUsed())
144  p_->~Base();
145  else
146  delete p_;
147  }
148  }
149 
150  void moveToWrappedObject(PolymorphicSmallObject&& other)
151  {
152  if (other.bufferUsed())
153  p_ = other.p_->move(&buffer_);
154  else
155  {
156  // We don't need to check for &other_!=this, because you can't
157  // have an rvalue to *this and call it's assignment/constructor
158  // at the same time. (Despite trying to shoot yourself in the foot
159  // with std::move explicitly.)
160 
161  // Take ownership of allocated object
162  p_ = other.p_;
163 
164  // Leave pointer in a clean state to avoid double freeing it.
165  other.p_ = 0;
166  }
167  }
168 
169  void copyToWrappedObject(const PolymorphicSmallObject& other)
170  {
171  if (other.bufferUsed())
172  p_ = other.p_->clone(&buffer_);
173  else
174  p_ = other.p_->clone();
175  }
176 
177  std::aligned_storage_t<bufferSize> buffer_;
178  Base* p_;
179 };
180 
181 
182 } // namespace Functions
183 } // namespace Dune
184 
185 #endif // DUNE_FUNCTIONS_COMMON_POLYMORPHICSMALLOBJECT_HH
Definition: polynomial.hh:10
A wrapper providing small object optimization with polymorphic types.
Definition: polymorphicsmallobject.hh:48
PolymorphicSmallObject & operator=(PolymorphicSmallObject &&other)
Move assignment from other PolymorphicSmallObject.
Definition: polymorphicsmallobject.hh:106
bool bufferUsed() const
Check if object is stored in internal stack buffer.
Definition: polymorphicsmallobject.hh:120
PolymorphicSmallObject(Derived &&derived)
Construct from object.
Definition: polymorphicsmallobject.hh:65
Base & get()
Obtain mutable reference to stored object.
Definition: polymorphicsmallobject.hh:132
PolymorphicSmallObject & operator=(const PolymorphicSmallObject &other)
Copy assignment from other PolymorphicSmallObject.
Definition: polymorphicsmallobject.hh:95
PolymorphicSmallObject(const PolymorphicSmallObject &other)
Copy constructor from other PolymorphicSmallObject.
Definition: polymorphicsmallobject.hh:83
~PolymorphicSmallObject()
Destructor.
Definition: polymorphicsmallobject.hh:89
const Base & get() const
Obtain reference to stored object.
Definition: polymorphicsmallobject.hh:126
PolymorphicSmallObject(PolymorphicSmallObject &&other)
Move constructor from other PolymorphicSmallObject.
Definition: polymorphicsmallobject.hh:77
PolymorphicSmallObject()
Default constructor.
Definition: polymorphicsmallobject.hh:52