Lumiera  0.pre.03
»edit your freedom«
replaceable-item.hpp
Go to the documentation of this file.
1 /*
2  REPLACEABLE-ITEM.hpp - adapter to take snapshot from non-assignable values
3 
4  Copyright (C) Lumiera.org
5  2017, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 */
22 
58 #ifndef LIB_REPLACEABLE_ITEM_H
59 #define LIB_REPLACEABLE_ITEM_H
60 
61 #include "lib/error.hpp"
62 #include "lib/null-value.hpp"
63 #include "lib/meta/util.hpp"
64 #include "lib/util.hpp"
65 
66 #include <type_traits>
67 #include <utility>
68 #include <cstddef>
69 
70 
71 
72 namespace lib {
73 namespace wrapper {
74 
75  using util::isSameObject;
76  using util::unConst;
77  using std::forward;
78 
79 
80 
81 
87  template<typename X, typename COND =void>
89  {
90  alignas(X)
91  std::byte content_[sizeof(X)];
92 
93  public:
95  {
96  emplace (NullValue<X>::get());
97  }
99  {
100  destroy();
101  }
102 
103  template<typename Z>
104  ReplaceableItem (Z&& otherValue)
105  {
106  emplace (forward<Z> (otherValue));
107  }
108 
109  template<typename Z>
111  operator= (Z&& otherValue)
112  {
113  if (not isSameObject(*this, otherValue))
114  reAssign (forward<Z> (otherValue));
115  return *this;
116  }
117 
119  clear() noexcept
120  {
121  reAssign (NullValue<X>::get());
122  return *this;
123  }
124 
125  operator X&() { return access(); }
126  operator X const&() const { return unConst(this)->access(); }
127 
128  X& get() { return access(); }
129  X const& get() const { return unConst(this)->access(); }
130 
131 
132  private:
133  X&
134  access()
135  {
136  return * std::launder (reinterpret_cast<X*> (&content_));
137  }
138 
139  void
140  destroy()
141  {
142  access().~X();
143  }
144 
145  template<typename Z>
146  void
147  emplace (Z&& otherValue)
148  try {
149  new(&content_) X{forward<Z> (otherValue)};
150  }
151  catch(...) {
152  new(&content_) X{NullValue<X>::get()};
153  }
154 
155  template<typename Z>
156  void
157  reAssign (Z&& otherValue)
158  {
159  destroy();
160  emplace (forward<Z> (otherValue));
161  }
162  };
163 
164 
165 
166  template<typename X>
168  : std::__and_<std::is_copy_assignable<X>, std::__not_<std::is_reference<X>>>
169  { };
170 
175  template<typename X>
176  class ReplaceableItem<X, meta::enable_if<is_assignable_value<X>>>
177  {
178  X val_;
179 
180  public:
181  ReplaceableItem() : val_(NullValue<X>::get()) { }
182 
183  ReplaceableItem(X const& val) : val_(val) { }
184  ReplaceableItem(X && val) : val_(forward<X>(val)) { }
185 
186  ReplaceableItem& operator= (X const& val) { val_=val; return *this; }
187  ReplaceableItem& operator= (X && val) { val_=forward<X>(val); return *this; }
188  ReplaceableItem& clear() noexcept { val_=NullValue<X>::get(); return *this; }
189 
190  operator X&() { return val_; }
191  operator X const&() const { return val_; }
192 
193  X& get() { return val_; }
194  X const& get() const { return val_; }
195  };
196 
197 
199  template<typename X>
200  class ReplaceableItem<X, meta::enable_if<std::is_reference<X>>>
201  {
202  static_assert( not sizeof(X), "ReplaceableItem for references is pointless");
203  };
204 
205 
206  /* ===== Equality comparison delegated to contained element ===== */
207 
208  template<typename X>
209  inline bool
211  {
212  return li.get() == ri.get();
213  }
214  template<typename X>
215  inline bool
216  operator!= (ReplaceableItem<X> const& li, ReplaceableItem<X> const& ri)
217  {
218  return li.get() != ri.get();
219  }
220 
221  template<typename X, typename Z>
222  inline bool
223  operator== (ReplaceableItem<X> const& item, Z const& something)
224  {
225  return item.get() == something;
226  }
227  template<typename X, typename Z>
228  inline bool
229  operator!= (ReplaceableItem<X> const& item, Z const& something)
230  {
231  return item.get() != something;
232  }
233 
234  template<typename Z, typename X>
235  inline bool
236  operator== (Z const& something, ReplaceableItem<X> const& item)
237  {
238  return item.get() == something;
239  }
240  template<typename Z, typename X>
241  inline bool
242  operator!= (Z const& something, ReplaceableItem<X> const& item)
243  {
244  return item.get() != something;
245  }
246 
247 
248 
249 }} // namespace lib::wrap
250 #endif /*LIB_REPLACEABLE_ITEM_H*/
Simple and lightweight helpers for metaprogramming and type detection.
bool operator==(PtrDerefIter< I1 > const &il, PtrDerefIter< I2 > const &ir)
Supporting equality comparisons...
Singleton holder for NIL or default value objects.
Definition: null-value.hpp:71
Singleton-style holder for NIL or default values.
Implementation namespace for support and library code.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
Lumiera error handling (C++ interface).
Adapter container to take snapshots from non-assignable values.
bool isSameObject(A const &a, B const &b)
compare plain object identity, bypassing any custom comparison operators.
Definition: util.hpp:372