dune-functions  2.5-dev
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 
8 namespace Dune {
9 namespace Functions {
10 
11 
37 template<class Base, size_t bufferSize>
39 {
40 public:
41 
44  p_(nullptr)
45  {}
46 
53  template<class Derived>
54  PolymorphicSmallObject(Derived&& derived)
55  {
56  if (sizeof(Derived)<bufferSize)
57  p_ = new (buffer_) Derived(std::forward<Derived>(derived));
58  else
59  p_ = new Derived(std::forward<Derived>(derived));
60  }
61 
64  {
65  moveToWrappedObject(std::move(other));
66  }
67 
70  {
71  copyToWrappedObject(other);
72  }
73 
76  {
77  destroyWrappedObject();
78  }
79 
82  {
83  destroyWrappedObject();
84  copyToWrappedObject(other);
85  return *this;
86  }
87 
90  {
91  destroyWrappedObject();
92  moveToWrappedObject(std::move(other));
93  return *this;
94  }
95 
97  explicit operator bool() const
98  {
99  return p_;
100  }
101 
103  bool bufferUsed() const
104  {
105  return ((void*) (p_) == (void*)(&buffer_));
106  }
107 
109  const Base& get() const
110  {
111  return *p_;
112  }
113 
115  Base& get()
116  {
117  return *p_;
118  }
119 
120 private:
121 
122  void destroyWrappedObject()
123  {
124  if (operator bool())
125  {
126  if (bufferUsed())
127  p_->~Base();
128  else
129  delete p_;
130  }
131  }
132 
133  void moveToWrappedObject(PolymorphicSmallObject&& other)
134  {
135  if (other.bufferUsed())
136  p_ = other.p_->move(buffer_);
137  else
138  {
139  // We don't need to check for &other_!=this, because you can't
140  // have an rvalue to *this and call it's assignment/constructor
141  // at the same time. (Despite trying to shot yourself in the foot
142  // with std::move explicitly.)
143 
144  // Take ownership of allocated object
145  p_ = other.p_;
146 
147  // Leave pointer in a clear state to avoid double freeing it.
148  other.p_ = 0;
149  }
150  }
151 
152  void copyToWrappedObject(const PolymorphicSmallObject& other)
153  {
154  if (&other!=this)
155  {
156  if (other.bufferUsed())
157  p_ = other.p_->clone(buffer_);
158  else
159  p_ = other.p_->clone();
160  }
161  }
162 
163  alignas(Base) char buffer_[bufferSize];
164  Base* p_;
165 };
166 
167 
168 } // namespace Functions
169 } // namespace Dune
170 
171 #endif // DUNE_FUNCTIONS_COMMON_POLYMORPHICSMALLOBJECT_HH
Definition: polynomial.hh:7
PolymorphicSmallObject & operator=(PolymorphicSmallObject &&other)
Move assignment from other PolymorphicSmallObject.
Definition: polymorphicsmallobject.hh:89
PolymorphicSmallObject()
Default constructor.
Definition: polymorphicsmallobject.hh:43
~PolymorphicSmallObject()
Destructor.
Definition: polymorphicsmallobject.hh:75
PolymorphicSmallObject(const PolymorphicSmallObject &other)
Copy constructor from other PolymorphicSmallObject.
Definition: polymorphicsmallobject.hh:69
PolymorphicSmallObject & operator=(const PolymorphicSmallObject &other)
Copy assignment from other PolymorphicSmallObject.
Definition: polymorphicsmallobject.hh:81
PolymorphicSmallObject(Derived &&derived)
Construct from object.
Definition: polymorphicsmallobject.hh:54
bool bufferUsed() const
Check if object is stored in internal stack buffer.
Definition: polymorphicsmallobject.hh:103
A wrapper providing small object optimization with polymorphic types.
Definition: polymorphicsmallobject.hh:38
PolymorphicSmallObject(PolymorphicSmallObject &&other)
Move constructor from other PolymorphicSmallObject.
Definition: polymorphicsmallobject.hh:63