Lumiera  0.pre.03
»edit your freedom«
wrapper.hpp
Go to the documentation of this file.
1 /*
2  WRAPPER.hpp - some smart wrapping and reference managing helper templates
3 
4  Copyright (C)
5  2009, 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 
32 #ifndef LIB_WRAPPER_H
33 #define LIB_WRAPPER_H
34 
35 #include "lib/error.hpp"
36 #include "lib/nocopy.hpp"
37 #include "lib/meta/function.hpp"
39 #include "lib/meta/util.hpp"
40 #include "lib/util.hpp"
41 
42 #include <functional>
43 #include <cstddef>
44 
45 
46 namespace lib {
47 namespace wrapper {
48 
49  using util::unConst;
50  using util::isSameObject;
51  using lib::meta::_Fun;
52  using LERR_(BOTTOM_VALUE);
53 
54  using std::function;
55 
56 
57 
62  template<typename T>
63  class ReturnRef
64  {
65  T& ref_;
66 
67  public:
68  ReturnRef(T& target) : ref_(target) { }
69  T& operator() () const { return ref_;}
70  };
71 
72  template<typename T>
74  refFunction (T& target)
75  {
76  return ReturnRef<T> (target);
77  }
78 
79 
80 
81 
82 
83 
101  template<typename TY>
103  {
104 
105  using TY_unconst = std::remove_const_t<TY>;
106 
107 
108  alignas(TY) mutable
109  std::byte content_[sizeof(TY)];
110 
111  bool created_;
112 
113  template<typename REF>
114  void
115  build (REF&& ref)
116  {
117  new(&content_) TY{std::forward<REF> (ref)};
118  created_ = true;
119  }
120 
121  void
122  discard ()
123  {
124  if (created_) access().~TY();
125  created_ = false;
126  }
127 
128  TY&
129  access () const
130  {
131  return * std::launder (reinterpret_cast<TY*> (&content_));
132  }
133 
134  TY_unconst&
135  access_unconst() const
136  {
137  return const_cast<TY_unconst&> (access());
138  }
139 
140  public:
141  ItemWrapper()
142  : created_(false)
143  { }
144 
145  explicit
146  ItemWrapper(TY const& o)
147  : created_(false)
148  {
149  build (o);
150  }
151  explicit
152  ItemWrapper(TY && ro)
153  : created_(false)
154  {
155  build (std::move(ro));
156  }
157 
158  ~ItemWrapper()
159  {
160  discard();
161  }
162 
163 
164  /* == copy and assignment == */
165 
166  ItemWrapper (ItemWrapper const& ref)
167  : created_(false)
168  {
169  if (ref.isValid())
170  build (*ref);
171  }
172  ItemWrapper (ItemWrapper && rref)
173  : created_(false)
174  {
175  if (rref.isValid())
176  {
177  build (std::move (*rref));
178  rref.discard();
179  }
180  }
181 
182  ItemWrapper&
183  operator= (ItemWrapper const& cref)
184  {
185  if (!cref.isValid())
186  discard();
187  else
188  this->operator= (*cref);
189 
190  return *this;
191  }
192  ItemWrapper&
193  operator= (ItemWrapper & ref)
194  {
195  return *this = (ItemWrapper const&)ref;
196  }
197  ItemWrapper&
198  operator= (ItemWrapper && rref)
199  {
200  if (!rref.isValid())
201  discard();
202  else
203  {
204  this->operator= (std::move(*rref));
205  rref.discard();
206  }
207 
208  return *this;
209  }
210 
219  template<typename X>
220  ItemWrapper&
221  operator= (X&& something)
222  {
223  if (!isSameObject (something, access() ))
224  {
225  discard();
226  build (std::forward<X>(something));
227  }
228  return *this;
229  }
230 
232  ItemWrapper&
234  {
235  discard();
236  build (TY());
237  return *this;
238  }
239 
240  operator bool() const
241  {
242  return isValid();
243  }
244 
245 
246  /* == value access == */
247  TY&
248  operator* () const
249  {
250  if (!created_)
251  throw lumiera::error::State ("accessing uninitialised value/ref wrapper"
252  , LERR_(BOTTOM_VALUE));
253  return access();
254  }
255 
256  TY*
257  operator-> () const
258  {
259  return & **this;
260  }
261 
262  bool
263  isValid () const
264  {
265  return created_;
266  }
267 
268  void
269  reset ()
270  {
271  discard();
272  }
273  };
274 
275 
281  template<typename TY>
282  class ItemWrapper<TY &>
283  {
284 
285  TY * content_;
286 
287 
288  public:
289  ItemWrapper()
290  : content_()
291  { }
292 
293  explicit
294  ItemWrapper(TY& o)
295  : content_( &o )
296  { }
297 
298  // using default copy and assignment
299 
300  operator bool() const { return isValid(); }
301 
302 
304  ItemWrapper&
305  operator= (TY& otherRef)
306  {
307  content_ = &otherRef;
308  return *this;
309  }
310 
311  ItemWrapper&
312  defaultInit()
313  {
314  reset();
315  return *this;
316  }
317 
318 
319  /* == value access == */
320  TY&
321  operator* () const
322  {
323  if (!content_)
324  throw lumiera::error::State ("accessing uninitialised reference wrapper"
325  , LERR_(BOTTOM_VALUE));
326  return *content_;
327  }
328 
329  bool
330  isValid () const
331  {
332  return bool(content_);
333  }
334 
335  void
336  reset ()
337  {
338  content_ = 0;
339  }
340  };
341 
342 
348  template<>
349  class ItemWrapper<void>
350  {
351  public:
352  ItemWrapper()
353  { }
354 
355  // using default copy and assignment
356 
357  operator bool() const { return true; }
358  bool isValid () const { return true; }
359  void reset () { /* NOP */ }
360 
362  void operator*() const { /* NOP */ }
363 
364  ItemWrapper&
365  defaultInit()
366  {
367  return *this;
368  }
369  };
370 
371 
372 
374  template<typename TY>
375  inline bool
377  {
378  return (!w1 && !w2)
379  || ( w1 && w2 && (*w1)==(*w2));
380  }
381  template<typename TY>
382  inline bool
383  operator!= (ItemWrapper<TY> const& w1, ItemWrapper<TY> const& w2)
384  {
385  return not (w1 == w2);
386  }
387 
388 
389 
390 
400  template<typename SIG>
402  : public function<SIG>
404  {
405  using Res = typename _Fun<SIG>::Ret;
407 
408  ResWrapper lastResult_;
409 
410  public:
412  FunctionResult() = default;
413 
420  template<typename FUN>
421  FunctionResult (FUN&& targetFunction)
422  : function<SIG>{lib::meta::func::chained
423  ( std::forward<FUN> (targetFunction)
424  , [this](Res res) -> Res
425  {
426  lastResult_ = res;
427  return std::forward<Res> (res);
428  })}
429  { }
430 
432  Res& operator*() const { return *lastResult_; }
433  bool isValid () const { return lastResult_.isValid(); }
434 
435  explicit
436  operator bool() const { return isValid(); }
437  };
438 
439 
440 }} // namespace lib::wrap
441 #endif
Reference wrapper implemented as constant function, returning the (fixed) reference on invocation...
Definition: wrapper.hpp:63
TY_unconst & access_unconst() const
< used to assign new buffer contents
Definition: wrapper.hpp:135
Simple and lightweight helpers for metaprogramming and type detection.
Any copy and copy construction prohibited.
Definition: nocopy.hpp:37
FunctionResult(FUN &&targetFunction)
Create result-remembering functor by outfitting a copy of the given function with an adaptor to captu...
Definition: wrapper.hpp:421
bool operator==(PtrDerefIter< I1 > const &il, PtrDerefIter< I2 > const &ir)
Supporting equality comparisons...
Helper for uniform access to function signature types.
Definition: function.hpp:99
Partial function application and building a complete function closure.
Universal value/ref wrapper accessible similar to a pointer.
Definition: wrapper.hpp:102
Implementation namespace for support and library code.
ItemWrapper & defaultInit()
implant a default-initialised instance of the payload type
Definition: wrapper.hpp:233
Derived specific exceptions within Lumiera&#39;s exception hierarchy.
Definition: error.hpp:190
Mix-Ins to allow or prohibit various degrees of copying and cloning.
Metaprogramming tools for transforming functor types.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
Extension of ItemWrapper: a function remembering the result of the last invocation.
Definition: wrapper.hpp:401
Lumiera error handling (C++ interface).
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