Dash Core Source Documentation (0.16.0.1)

Find detailed information regarding the Dash Core source code.

box.hpp
Go to the documentation of this file.
1 //
2 // immer: immutable data structures for C++
3 // Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
4 //
5 // This software is distributed under the Boost Software License, Version 1.0.
6 // See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
7 //
8 
9 #pragma once
10 
11 #include <immer/detail/util.hpp>
12 #include <immer/memory_policy.hpp>
13 
14 namespace immer {
15 
16 namespace detail {
17 
18 template <typename U, typename MP>
19 struct gc_atom_impl;
20 
21 template <typename U, typename MP>
22 struct refcount_atom_impl;
23 
24 } // namespace detail
25 
33 template <typename T,
34  typename MemoryPolicy = default_memory_policy>
35 class box
36 {
37  friend struct detail::gc_atom_impl<T, MemoryPolicy>;
38  friend struct detail::refcount_atom_impl<T, MemoryPolicy>;
39 
40  struct holder : MemoryPolicy::refcount
41  {
42  T value;
43 
44  template <typename... Args>
45  holder(Args&&... args) : value{std::forward<Args>(args)...} {}
46  };
47 
48  using heap = typename MemoryPolicy::heap::type;
49 
50  holder* impl_ = nullptr;
51 
52  box(holder* impl) : impl_{impl} {}
53 
54 public:
55  using value_type = T;
56  using memory_policy = MemoryPolicy;
57 
61  box() : impl_{detail::make<heap, holder>()} {}
62 
66  template <typename Arg,
67  typename Enable=std::enable_if_t<
68  !std::is_same<box, std::decay_t<Arg>>::value &&
69  std::is_constructible<T, Arg>::value>>
70  box(Arg&& arg)
71  : impl_{detail::make<heap, holder>(std::forward<Arg>(arg))} {}
72 
76  template <typename Arg1, typename Arg2, typename... Args>
77  box(Arg1&& arg1, Arg2&& arg2, Args&& ...args)
78  : impl_{detail::make<heap, holder>(
79  std::forward<Arg1>(arg1),
80  std::forward<Arg2>(arg2),
81  std::forward<Args>(args)...)}
82  {}
83 
84  friend void swap(box& a, box& b)
85  { using std::swap; swap(a.impl_, b.impl_); }
86 
87  box(box&& other) { swap(*this, other); }
88  box(const box& other) : impl_(other.impl_) { impl_->inc(); }
89  box& operator=(box&& other) { swap(*this, other); return *this; }
90  box& operator=(const box& other)
91  {
92  auto aux = other;
93  swap(*this, aux);
94  return *this;
95  }
96  ~box()
97  {
98  if (impl_ && impl_->dec()) {
99  impl_->~holder();
100  heap::deallocate(sizeof(holder), impl_);
101  }
102  }
103 
105  const T& get() const { return impl_->value; }
106 
108  operator const T&() const { return get(); }
109 
111  const T& operator* () const { return get(); }
112 
114  const T* operator-> () const { return &get(); }
115 
118  { return impl_ == other.value.impl_ || get() == other.value.get(); }
119  // Note that the `exact_t` disambiguates comparisons against `T{}`
120  // directly. In that case we want to use `operator T&` and
121  // compare directly. We definitely never want to convert a value
122  // to a box (which causes an allocation) just to compare it.
124  { return !(*this == other.value); }
125  bool operator<(detail::exact_t<const box&> other) const
126  { return get() < other.value.get(); }
127 
143  template <typename Fn>
144  box update(Fn&& fn) const&
145  {
146  return std::forward<Fn>(fn)(get());
147  }
148  template <typename Fn>
149  box&& update(Fn&& fn) &&
150  {
151  if (impl_->unique())
152  impl_->value = std::forward<Fn>(fn)(std::move(impl_->value));
153  else
154  *this = std::forward<Fn>(fn)(impl_->value);
155  return std::move(*this);
156  }
157 };
158 
159 } // namespace immer
160 
161 namespace std {
162 
163 template <typename T, typename MP>
164 struct hash<immer::box<T, MP>>
165 {
166  std::size_t operator() (const immer::box<T, MP>& x) const
167  {
168  return std::hash<T>{}(*x);
169  }
170 };
171 
172 } // namespace std
box(Arg1 &&arg1, Arg2 &&arg2, Args &&...args)
Definition: box.hpp:77
box && update(Fn &&fn) &&
Definition: box.hpp:149
box(holder *impl)
Definition: box.hpp:52
friend void swap(box &a, box &b)
Definition: box.hpp:84
Definition: box.hpp:161
typename MemoryPolicy::heap::type heap
Definition: box.hpp:48
box(Arg &&arg)
Definition: box.hpp:70
holder * impl_
Definition: box.hpp:50
bool operator==(detail::exact_t< const box &> other) const
Definition: box.hpp:117
box update(Fn &&fn) const &
Definition: box.hpp:144
T value_type
Definition: box.hpp:55
std::size_t size_t
Definition: bits.hpp:21
~box()
Definition: box.hpp:96
box & operator=(box &&other)
Definition: box.hpp:89
box(box &&other)
Definition: box.hpp:87
memory_policy< default_heap_policy, default_refcount_policy > default_memory_policy
box & operator=(const box &other)
Definition: box.hpp:90
const T & operator*() const
Definition: box.hpp:111
bool operator!=(detail::exact_t< const box &> other) const
Definition: box.hpp:123
box(const box &other)
Definition: box.hpp:88
MemoryPolicy memory_policy
Definition: box.hpp:56
box()
Definition: box.hpp:61
holder(Args &&... args)
Definition: box.hpp:45
const T * operator->() const
Definition: box.hpp:114
Released under the MIT license