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)
5  2017, Hermann Vosseler <Ichthyostega@web.de>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 */
13 
49 #ifndef LIB_REPLACEABLE_ITEM_H
50 #define LIB_REPLACEABLE_ITEM_H
51 
52 #include "lib/error.hpp"
53 #include "lib/null-value.hpp"
54 #include "lib/meta/util.hpp"
55 #include "lib/util.hpp"
56 
57 #include <type_traits>
58 #include <utility>
59 #include <cstddef>
60 
61 
62 
63 namespace lib {
64 namespace wrapper {
65 
66  using util::isSameObject;
67  using util::unConst;
68  using std::forward;
69 
70 
71 
72 
78  template<typename X, typename COND =void>
80  {
81  alignas(X)
82  std::byte content_[sizeof(X)];
83 
84  public:
86  {
87  emplace (NullValue<X>::get());
88  }
90  {
91  destroy();
92  }
93 
94  template<typename Z>
95  ReplaceableItem (Z&& otherValue)
96  {
97  emplace (forward<Z> (otherValue));
98  }
99 
100  template<typename Z>
102  operator= (Z&& otherValue)
103  {
104  if (not isSameObject(*this, otherValue))
105  reAssign (forward<Z> (otherValue));
106  return *this;
107  }
108 
110  clear() noexcept
111  {
112  reAssign (NullValue<X>::get());
113  return *this;
114  }
115 
116  operator X&() { return access(); }
117  operator X const&() const { return unConst(this)->access(); }
118 
119  X& get() { return access(); }
120  X const& get() const { return unConst(this)->access(); }
121 
122 
123  private:
124  X&
125  access()
126  {
127  return * std::launder (reinterpret_cast<X*> (&content_));
128  }
129 
130  void
131  destroy()
132  {
133  access().~X();
134  }
135 
136  template<typename Z>
137  void
138  emplace (Z&& otherValue)
139  try {
140  new(&content_) X{forward<Z> (otherValue)};
141  }
142  catch(...) {
143  new(&content_) X{NullValue<X>::get()};
144  }
145 
146  template<typename Z>
147  void
148  reAssign (Z&& otherValue)
149  {
150  destroy();
151  emplace (forward<Z> (otherValue));
152  }
153  };
154 
155 
156 
157  template<typename X>
159  : std::__and_<std::is_copy_assignable<X>, std::__not_<std::is_reference<X>>>
160  { };
161 
166  template<typename X>
167  class ReplaceableItem<X, meta::enable_if<is_assignable_value<X>>>
168  {
169  X val_;
170 
171  public:
172  ReplaceableItem() : val_(NullValue<X>::get()) { }
173 
174  ReplaceableItem(X const& val) : val_(val) { }
175  ReplaceableItem(X && val) : val_(forward<X>(val)) { }
176 
177  ReplaceableItem& operator= (X const& val) { val_=val; return *this; }
178  ReplaceableItem& operator= (X && val) { val_=forward<X>(val); return *this; }
179  ReplaceableItem& clear() noexcept { val_=NullValue<X>::get(); return *this; }
180 
181  operator X&() { return val_; }
182  operator X const&() const { return val_; }
183 
184  X& get() { return val_; }
185  X const& get() const { return val_; }
186  };
187 
188 
190  template<typename X>
191  class ReplaceableItem<X, meta::enable_if<std::is_reference<X>>>
192  {
193  static_assert( not sizeof(X), "ReplaceableItem for references is pointless");
194  };
195 
196 
197  /* ===== Equality comparison delegated to contained element ===== */
198 
199  template<typename X>
200  inline bool
202  {
203  return li.get() == ri.get();
204  }
205  template<typename X>
206  inline bool
207  operator!= (ReplaceableItem<X> const& li, ReplaceableItem<X> const& ri)
208  {
209  return li.get() != ri.get();
210  }
211 
212  template<typename X, typename Z>
213  inline bool
214  operator== (ReplaceableItem<X> const& item, Z const& something)
215  {
216  return item.get() == something;
217  }
218  template<typename X, typename Z>
219  inline bool
220  operator!= (ReplaceableItem<X> const& item, Z const& something)
221  {
222  return item.get() != something;
223  }
224 
225  template<typename Z, typename X>
226  inline bool
227  operator== (Z const& something, ReplaceableItem<X> const& item)
228  {
229  return item.get() == something;
230  }
231  template<typename Z, typename X>
232  inline bool
233  operator!= (Z const& something, ReplaceableItem<X> const& item)
234  {
235  return item.get() != something;
236  }
237 
238 
239 
240 }} // namespace lib::wrap
241 #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:62
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, based directly on the referee&#39;s memory identities. ...
Definition: util.hpp:421