libjmmcg  release_579_6_g8cffd
A C++ library containing an eclectic mix of useful, advanced components.
unique_ptr_impl.hpp
Go to the documentation of this file.
1 /******************************************************************************
2 ** Copyright © 2015 by J.M.McGuiness, coder@hussar.me.uk
3 **
4 ** This library is free software; you can redistribute it and/or
5 ** modify it under the terms of the GNU Lesser General Public
6 ** License as published by the Free Software Foundation; either
7 ** version 2.1 of the License, or (at your option) any later version.
8 **
9 ** This library is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 ** Lesser General Public License for more details.
13 **
14 ** You should have received a copy of the GNU Lesser General Public
15 ** License along with this library; if not, write to the Free Software
16 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18 
19 #include <boost/mpl/assert.hpp>
20 
21 namespace jmmcg { namespace LIBJMMCG_VER_NAMESPACE {
22 
23  template<class V, class LkT> inline typename unique_ptr<V, LkT>::atomic_ptr_t
24  unique_ptr<V, LkT>::release() noexcept(true) {
25  atomic_ptr_t tmp(nullptr);
26  tmp.swap(this->data_);
27  return tmp;
28  }
29 
30  template<class V, class LkT> inline void
31  unique_ptr<V, LkT>::reset() noexcept(true) {
32  unique_ptr tmp;
33  tmp.swap(*this);
34  }
35 
36  template<class V, class LkT> inline void
37  unique_ptr<V, LkT>::swap(unique_ptr &s) noexcept(true) {
38  data_.swap(s.data_);
39  }
40 
41  template<class V, class LkT>
42  template<class V1> inline void
43  unique_ptr<V, LkT>::swap(unique_ptr<V1, LkT> &s) noexcept(true) {
44  BOOST_MPL_ASSERT((std::is_base_of<value_type, V1>));
45  data_.swap(s.data_);
46  }
47 
48  template<class V, class LkT>
49  template<class V2, class LkT2> inline void
50  unique_ptr<V, LkT>::swap(unique_ptr<V2, LkT2> &s) noexcept(true) {
51  BOOST_MPL_ASSERT((std::is_base_of<value_type, V2>));
52  data_.swap(s.data_);
53  }
54 
55  template<class V, class LkT> inline constexpr
56  unique_ptr<V, LkT>::unique_ptr(value_type *ptr) noexcept(true)
57  : data_(ptr) {
58  }
59 
60  template<class V, class LkT>
61  template<class V1>
62  inline
63  unique_ptr<V, LkT>::unique_ptr(V1 *ptr) noexcept(true)
64  : data_(ptr) {
65  BOOST_MPL_ASSERT((std::is_base_of<value_type, V1>));
66  }
67 
68  template<class V, class LkT> inline
69  unique_ptr<V, LkT>::unique_ptr(atomic_ptr_t &&ptr) noexcept(true)
70  : data_(nullptr) {
71  BOOST_MPL_ASSERT((std::is_base_of<value_type, typename atomic_ptr_t::value_type>));
72  data_.swap(ptr);
73  }
74 
75  template<class V, class LkT>
76  template<class V1, template<class> class At>
77  inline
78  unique_ptr<V, LkT>::unique_ptr(At<V1*> &&ptr) noexcept(true)
79  : data_(nullptr) {
80  BOOST_MPL_ASSERT((std::is_base_of<value_type, V1>));
81  if (LIKELY(ptr.get())) {
82  assert(dynamic_cast<V1 *>(ptr.get()));
83  data_.swap(ptr);
84  assert(dynamic_cast<value_type *>(data_.get()));
85  }
86  }
87 
88  template<class V, class LkT> inline constexpr
89  unique_ptr<V, LkT>::unique_ptr(std::unique_ptr<value_type, deleter_t> &&d) noexcept(true)
90  : data_(d.release()) {
91  }
92 
93  template<class V, class LkT>
94  template<class V1>
95  inline
96  unique_ptr<V, LkT>::unique_ptr(std::unique_ptr<V1, typename V1::deleter_t> &&d) noexcept(true)
97  : data_(d.release()) {
98  BOOST_MPL_ASSERT((std::is_base_of<value_type, V1>));
99  // I want to test that if the dtor is dynamic alloc, then the V1::element_type is derived from value_type, otherwise if placement, the dtor must be the same, otherwise if noop_dtor, don't care.
100 // This is too stringent a test, as it ignores virtual dtors: BOOST_MPL_ASSERT((std::is_same<deleter_t, typename V1::deleter_t>));
101 // static_assert(std::is_base_of<deleter_t, typename V1::deleter_t>::value || std::is_base_of<typename V1::deleter_t, deleter_t>::value, "TODO");
102  }
103 
104  template<class V, class LkT> inline constexpr
105  unique_ptr<V, LkT>::unique_ptr(unique_ptr &&s) noexcept(true)
106  : data_(s.release()) {
107  }
108 
109  template<class V, class LkT>
110  template<typename V2, class LkT2> inline
111  unique_ptr<V, LkT>::unique_ptr(unique_ptr<V2, LkT2> &&s) noexcept(true)
112  : data_(s.release()) {
113  BOOST_MPL_ASSERT((std::is_base_of<value_type, V2>));
114  }
115 
116  template<class V, class LkT> inline
117  unique_ptr<V, LkT>::~unique_ptr() noexcept(true) {
118  atomic_ptr_t tmp(nullptr);
119  tmp.swap(this->data_);
120  if (tmp) {
121  tmp->deleter();
122  }
123  }
124 
125  template<class V, class LkT>
126  template<typename V2, class LkT2> inline void
127  unique_ptr<V, LkT>::operator=(unique_ptr<V2, LkT2> &&s) noexcept(true) {
128  BOOST_MPL_ASSERT((std::is_base_of<value_type, V2>));
129  reset();
130  data_=s.release();
131  }
132 
133  template<class V, class LkT> inline void
134  unique_ptr<V, LkT>::operator=(unique_ptr<V, LkT> &&s) noexcept(true) {
135  reset();
136  data_=s.release();
137  }
138 
139  template<class V, class LkT> constexpr inline bool
140  unique_ptr<V, LkT>::operator<(const unique_ptr &s) const noexcept(true) {
141  return (data_.get() && s.data_.get()) ? (*data_.get()<*s.data_.get()) : false;
142  }
143  template<class V, class LkT> constexpr inline bool
144  unique_ptr<V, LkT>::operator==(const unique_ptr &s) const noexcept(true) {
145  return !((data_<s.data_) || (s.data_<data_));
146  }
147  template<class V, class LkT> inline constexpr bool
148  unique_ptr<V, LkT>::operator!=(const unique_ptr &s) const noexcept(true) {
149  return !(*this==s);
150  }
151  template<class V, class LkT> constexpr inline
152  unique_ptr<V, LkT>::operator bool() const noexcept(true) {
153  return dynamic_cast<value_type const *>(data_.get())!=nullptr;
154  }
155  template<class V, class LkT> constexpr inline bool
156  unique_ptr<V, LkT>::operator>(const unique_ptr &s) const noexcept(true) {
157  return (data_!=s.data_) && (s.data_<data_);
158  }
159 
160  template<class V, class LkT> constexpr inline typename unique_ptr<V, LkT>::atomic_ptr_t const &
161  unique_ptr<V, LkT>::get() const noexcept(true) {
162  return data_;
163  }
164  template<class V, class LkT> inline typename unique_ptr<V, LkT>::atomic_ptr_t &
165  unique_ptr<V, LkT>::get() noexcept(true) {
166  return data_;
167  }
168  template<class V, class LkT> constexpr inline typename unique_ptr<V, LkT>::value_type const &
169  unique_ptr<V, LkT>::operator*() const noexcept(true) {
170  assert(dynamic_cast<value_type const *>(data_.get()));
171  return *data_.get();
172  }
173  template<class V, class LkT> inline typename unique_ptr<V, LkT>::value_type &
174  unique_ptr<V, LkT>::operator*() noexcept(true) {
175  assert(dynamic_cast<value_type *>(data_.get()));
176  return *data_.get();
177  }
178  template<class V, class LkT> constexpr inline typename unique_ptr<V, LkT>::value_type const *
179  unique_ptr<V, LkT>::operator->() const noexcept(true) {
180  return data_.get();
181  }
182  template<class V, class LkT> inline typename unique_ptr<V, LkT>::value_type *
183  unique_ptr<V, LkT>::operator->() noexcept(true) {
184  return data_.get();
185  }
186 
187  template<class V, class LkT> inline tstring
188  unique_ptr<V, LkT>::to_string() const noexcept(false) {
189  tostringstream os;
190  os<<"data_="<<data_.get();
191  if (LIKELY(dynamic_cast<value_type *>(data_.get()))) {
192  os<<", data: "<<data_->to_string()
193  <<", type: "<<ppd::api_threading_traits<ppd::platform_api, ppd::sequential_mode>::demangle_name(typeid(unique_ptr));
194  }
195  return os.str();
196  }
197 
198 } }