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 
69 
70 
71 namespace lib {
72 namespace wrapper {
73 
74  using util::isSameObject;
75  using util::unConst;
76  using std::forward;
77 
78 
79 
80 
86  template<typename X, typename COND =void>
88  {
89  char content_[sizeof(X)];
90 
91  public:
93  {
94  emplace (NullValue<X>::get());
95  }
97  {
98  destroy();
99  }
100 
101  template<typename Z>
102  ReplaceableItem (Z&& otherValue)
103  {
104  emplace (forward<Z> (otherValue));
105  }
106 
107  template<typename Z>
109  operator= (Z&& otherValue)
110  {
111  if (not isSameObject(*this, otherValue))
112  reAssign (forward<Z> (otherValue));
113  return *this;
114  }
115 
117  clear() noexcept
118  {
119  reAssign (NullValue<X>::get());
120  return *this;
121  }
122 
123  operator X&() { return access(); }
124  operator X const&() const { return unConst(this)->access(); }
125 
126  X& get() { return access(); }
127  X const& get() const { return unConst(this)->access(); }
128 
129 
130  private:
131  X&
132  access()
133  {
134  return reinterpret_cast<X&>(content_);
135  }
136 
137  void
138  destroy()
139  {
140  access().~X();
141  }
142 
143  template<typename Z>
144  void
145  emplace (Z&& otherValue)
146  try {
147  new(&content_) X{forward<Z> (otherValue)};
148  }
149  catch(...) {
150  new(&content_) X{NullValue<X>::get()};
151  }
152 
153  template<typename Z>
154  void
155  reAssign (Z&& otherValue)
156  {
157  destroy();
158  emplace (forward<Z> (otherValue));
159  }
160  };
161 
162 
163 
164  template<typename X>
166  : std::__and_<std::is_copy_assignable<X>, std::__not_<std::is_reference<X>>>
167  { };
168 
173  template<typename X>
174  class ReplaceableItem<X, meta::enable_if<is_assignable_value<X>>>
175  {
176  X val_;
177 
178  public:
179  ReplaceableItem() : val_(NullValue<X>::get()) { }
180 
181  ReplaceableItem(X const& val) : val_(val) { }
182  ReplaceableItem(X && val) : val_(forward<X>(val)) { }
183 
184  ReplaceableItem& operator= (X const& val) { val_=val; return *this; }
185  ReplaceableItem& operator= (X && val) { val_=forward<X>(val); return *this; }
186  ReplaceableItem& clear() noexcept { val_=NullValue<X>::get(); return *this; }
187 
188  operator X&() { return val_; }
189  operator X const&() const { return val_; }
190 
191  X& get() { return val_; }
192  X const& get() const { return val_; }
193  };
194 
195 
197  template<typename X>
198  class ReplaceableItem<X, meta::enable_if<std::is_reference<X>>>
199  {
200  static_assert( not sizeof(X), "ReplaceableItem for references is pointless");
201  };
202 
203 
204  /* ===== Equality comparison delegated to contained element ===== */
205 
206  template<typename X>
207  inline bool
209  {
210  return li.get() == ri.get();
211  }
212  template<typename X>
213  inline bool
214  operator!= (ReplaceableItem<X> const& li, ReplaceableItem<X> const& ri)
215  {
216  return li.get() != ri.get();
217  }
218 
219  template<typename X, typename Z>
220  inline bool
221  operator== (ReplaceableItem<X> const& item, Z const& something)
222  {
223  return item.get() == something;
224  }
225  template<typename X, typename Z>
226  inline bool
227  operator!= (ReplaceableItem<X> const& item, Z const& something)
228  {
229  return item.get() != something;
230  }
231 
232  template<typename Z, typename X>
233  inline bool
234  operator== (Z const& something, ReplaceableItem<X> const& item)
235  {
236  return item.get() == something;
237  }
238  template<typename Z, typename X>
239  inline bool
240  operator!= (Z const& something, ReplaceableItem<X> const& item)
241  {
242  return item.get() != something;
243  }
244 
245 
246 
247 }} // namespace lib::wrap
248 #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:347