Turi Create  4.0
gl_vector.hpp
1 /* Copyright © 2017 Apple Inc. All rights reserved.
2  *
3  * Use of this source code is governed by a BSD-3-clause license that can
4  * be found in the LICENSE.txt file or at https://opensource.org/licenses/BSD-3-Clause
5  */
6 #ifndef TURI_GL_VECTOR_H_
7 #define TURI_GL_VECTOR_H_
8 
9 #include <core/generics/vector_internals.hpp>
10 #include <core/generics/vector_serialization.hpp>
11 #include <core/generics/is_memmovable.hpp>
12 #include <algorithm>
13 
14 namespace turi {
15 
16 template <typename _T>
17 class gl_vector {
18  static_assert(is_memmovable<_T>::value, "gl_vector requires T to be memmovable");
19  public:
20  typedef _T value_type;
21 
22  typedef value_type& reference;
23  typedef const value_type& const_reference;
24 
25  typedef value_type* pointer;
26  typedef const value_type* const_pointer;
27 
28  typedef value_type* iterator;
29  typedef const value_type* const_iterator;
30 
31  typedef std::reverse_iterator<value_type*> reverse_iterator;
32  typedef std::reverse_iterator<const value_type*> const_reverse_iterator;
33 
34  typedef ptrdiff_t difference_type;
35  typedef size_t size_type;
36 
37  // static constexpr _inplace_values_allowed() { return sizeof(value_type) <= (sizeof(void*) - 1); }
38  // static constexpr _max_num_inplace_values() { return (sizeof(void*) - 1) / sizeof(value_type); }
39 
40  private:
41 
42  /// The structur holding all the information
43  gl_vector_internal::_vstruct<value_type> *info;
44 
45  public:
46  template <class InputIterator>
47  gl_vector (InputIterator first, InputIterator last, _VEC_ENABLE_IF_ITERATOR(InputIterator, value_type))
48  : info(gl_vector_internal::construct<value_type, InputIterator>(first, last) )
49  {}
50 
51  gl_vector () noexcept
52  : info(nullptr)
53  {}
54 
55  explicit gl_vector (size_type n)
56  : info(gl_vector_internal::construct<value_type>(n))
57  {}
58 
59  gl_vector (size_type n, const value_type& val)
60  : info(gl_vector_internal::construct<value_type>(n, val))
61  {}
62 
63  gl_vector (gl_vector&& x) {
64  if(&x != this) {
65  info = x.info;
66  x.info = nullptr;
67  }
68  }
69 
70  gl_vector (const gl_vector& v)
71  : info(gl_vector_internal::construct<value_type>(v.begin(), v.end()))
72  {}
73 
74 
75  explicit gl_vector (const std::vector<value_type>& v)
76  : info(gl_vector_internal::construct<value_type>(v.begin(), v.end()))
77  {}
78 
79  gl_vector (std::initializer_list<value_type> il)
80  : info(gl_vector_internal::construct<value_type>(il.begin(), il.end()) )
81  {}
82 
83  template <typename T1>
84  gl_vector (std::initializer_list<T1> il, _VEC_ENABLE_IF_CONVERTABLE(T1, value_type))
85  : info(gl_vector_internal::construct<value_type>(il.begin(), il.end()) )
86  {}
87 
88  ~gl_vector() {
89  if(info != nullptr) {
90  gl_vector_internal::destroy(info);
91  info = nullptr;
92  }
93  }
94 
95  const gl_vector& operator=(const gl_vector& v) {
96  assign(v);
97  return *this;
98  }
99 
100  const gl_vector& operator=(gl_vector&& v) {
101  assign(std::move(v));
102  return *this;
103  }
104 
105  const gl_vector& operator=(std::initializer_list<value_type> il) {
106  assign(il);
107  return *this;
108  }
109 
110  // Do this to resolve annoying conflict resolution issues
111  template <typename T, typename = typename std::enable_if<std::is_same<T, value_type>::value>::type>
112  const gl_vector& operator=(const std::vector<T>& v) {
113  gl_vector_internal::assign(info, v.begin(), v.end());
114  return *this;
115  }
116 
117  operator std::vector<value_type>() const {
118  return std::vector<value_type>(cbegin(), cend());
119  }
120 
121  const_iterator begin() const noexcept { return gl_vector_internal::cbegin(info); }
122  iterator begin() noexcept { return gl_vector_internal::begin(info); }
123 
124  const_reverse_iterator rbegin() const noexcept {
125  return std::reverse_iterator<const_iterator>(end());
126  }
127 
128  reverse_iterator rbegin() noexcept {
129  return std::reverse_iterator<iterator>(end());
130  }
131 
132  const_iterator end() const noexcept { return gl_vector_internal::cend(info); }
133  iterator end() noexcept { return gl_vector_internal::end(info); }
134 
135  reverse_iterator rend() noexcept { return std::reverse_iterator<iterator>(begin()); }
136  const_reverse_iterator rend() const noexcept { return std::reverse_iterator<const_iterator>(begin()); }
137 
138  const_iterator cbegin() const noexcept { return begin(); }
139 
140  const_reverse_iterator crbegin() const noexcept { return rbegin(); }
141 
142  const_iterator cend() const noexcept { return end(); }
143 
144  const_reverse_iterator crend() const noexcept { return rend(); }
145 
146  size_type size() const noexcept { return gl_vector_internal::size(info); }
147 
148  size_type max_size() const noexcept { return std::numeric_limits<size_t>::max() / sizeof(value_type); }
149 
150  inline void resize (size_type n) {
151  if(gl_vector_internal::size(info) != n)
152  gl_vector_internal::resize(info, n);
153  DASSERT_EQ(gl_vector_internal::size(info), n);
154  }
155 
156  void resize (size_type n, const value_type& val) {
157  gl_vector_internal::resize(info, n, val);
158  }
159 
160  size_type capacity() const noexcept { return gl_vector_internal::capacity(info); }
161 
162  bool empty() const noexcept {
163  return size() == 0;
164  }
165 
166  void reserve (size_type n) {
167  gl_vector_internal::reserve(info, n);
168  }
169 
170  void shrink_to_fit() {
171  if(gl_vector_internal::has_excess_storage(info)) {
172  this->swap(gl_vector(this->begin(), this->end()));
173  }
174  }
175 
176  reference operator[] (size_type idx) _VEC_NDEBUG_NOEXCEPT {
177  return gl_vector_internal::get_element(info, idx);
178  }
179 
180  const_reference operator[] (size_type idx) const _VEC_NDEBUG_NOEXCEPT {
181  return gl_vector_internal::get_element(info, idx);
182  }
183 
184  reference at (size_type idx) _VEC_NDEBUG_NOEXCEPT {
185  return gl_vector_internal::get_element(info, idx);
186  }
187 
188  const_reference at (size_type idx) const _VEC_NDEBUG_NOEXCEPT {
189  return gl_vector_internal::get_element(info, idx);
190  }
191 
192  reference front() _VEC_NDEBUG_NOEXCEPT {
193  DASSERT_NE(gl_vector_internal::size(info), 0);
194  return gl_vector_internal::get_element(info, 0);
195  }
196 
197  const_reference front() const _VEC_NDEBUG_NOEXCEPT {
198  DASSERT_NE(gl_vector_internal::size(info), 0);
199  return gl_vector_internal::get_element(info, 0);
200  }
201 
202  reference back() _VEC_NDEBUG_NOEXCEPT {
203  DASSERT_NE(gl_vector_internal::size(info), 0);
204  return gl_vector_internal::get_element(info, info->size - 1);
205  }
206 
207  const_reference back() const _VEC_NDEBUG_NOEXCEPT {
208  DASSERT_NE(gl_vector_internal::size(info), 0);
209  return gl_vector_internal::get_element(info, info->size - 1);
210  }
211 
212  value_type* data() noexcept { return info == nullptr ? nullptr : info->data; }
213 
214  const value_type* data() const noexcept { return info == nullptr ? nullptr : info->data; }
215 
216  template <class InputIterator>
217  void assign (const InputIterator& first, const InputIterator& last,
218  _VEC_ENABLE_IF_ITERATOR(InputIterator, value_type)) {
219  gl_vector_internal::assign(info, first, last);
220  }
221 
222  void assign(size_type n, const value_type& val) {
223  gl_vector_internal::assign(info, n, val);
224  }
225 
226  void assign(std::initializer_list<value_type> il) {
227  gl_vector_internal::assign(info, il);
228  }
229 
230  void assign(const gl_vector& v) {
231  if(v.info != info)
232  gl_vector_internal::assign(info, v.begin(), v.end());
233  }
234 
235  void assign(gl_vector&& v) {
236  gl_vector_internal::assign_move(info, v.info);
237  }
238 
239  void push_back (const value_type& val) {
240  gl_vector_internal::push_back(info, val);
241  }
242 
243  void push_back (value_type&& val) {
244  gl_vector_internal::push_back(info, std::forward<value_type>(val));
245  }
246 
247  template <class... Args>
248  iterator emplace (const_iterator position, Args&&... args) {
249  return gl_vector_internal::emplace(info, position, args...);
250  }
251 
252  template <class... Args>
253  void emplace_back (Args&&... args) {
254  gl_vector_internal::emplace_back(info, args...);
255  }
256 
257  void pop_back() {
258  gl_vector_internal::pop_back(info);
259  }
260 
261  iterator insert (const_iterator position, size_type n, const value_type& val) {
262  return gl_vector_internal::insert(info, position, n, val);
263  }
264 
265  template <typename U>
266  iterator insert (const_iterator position, U&& val) {
267  return gl_vector_internal::insert(info, position, std::forward<U>(val));
268  }
269 
270  template <class InputIterator>
271  iterator insert (const_iterator position, InputIterator first, InputIterator last,
272  _VEC_ENABLE_IF_ITERATOR(InputIterator, value_type) ) {
273  DASSERT_GE(std::distance(first, last), 0);
274  return gl_vector_internal::insert(info, position, first, last);
275  }
276 
277  iterator insert (const_iterator position, std::initializer_list<value_type> il) {
278  return gl_vector_internal::insert(info, position, il.begin(), il.end());
279  }
280 
281  iterator erase (const_iterator position) {
282  return gl_vector_internal::erase(info, position);
283  }
284 
285  iterator erase (const_iterator first, const_iterator last) {
286  return gl_vector_internal::erase(info, first, last);
287  }
288 
289  void swap (gl_vector& x) noexcept {
290  std::swap(info, x.info);
291  }
292 
293  void swap (gl_vector&& x) noexcept {
294  std::swap(info, x.info);
295  }
296 
297  void clear() noexcept {
298  gl_vector_internal::clear(info);
299  }
300 
301 };
302 
303 ////////////////////////////////////////////////////////////////////////////////
304 // operator overloads
305 
306 template <class T>
307 bool operator== (const gl_vector<T>& lhs, const gl_vector<T>& rhs) {
308  return (lhs.size() == rhs.size()
309  && std::equal(lhs.begin(), lhs.end(), rhs.begin()));
310 }
311 
312 template <class T>
313 bool operator!= (const gl_vector<T>& lhs, const gl_vector<T>& rhs) {
314  return !(lhs == rhs);
315 }
316 
317 
318 template <typename T>
319 struct is_memmovable<gl_vector<T>> {
320  static constexpr bool value = is_memmovable<T>::value;
321 };
322 
323 } // turi
324 
325 namespace std {
326 
327 template <class T>
328 inline void swap (turi::gl_vector<T>& a, turi::gl_vector<T>& b) noexcept {
329  a.swap(b);
330 }
331 
332 }
333 
334 
335 #endif /* TURI_GL_VECTOR_H_ */
STL namespace.