Dash Core Source Documentation (0.16.0.1)

Find detailed information regarding the Dash Core source code.

node.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 
12 #include <immer/detail/util.hpp>
14 
15 #include <cassert>
16 
17 #ifdef NDEBUG
18 #define IMMER_HAMTS_TAGGED_NODE 0
19 #else
20 #define IMMER_HAMTS_TAGGED_NODE 1
21 #endif
22 
23 namespace immer {
24 namespace detail {
25 namespace hamts {
26 
27 template <typename T,
28  typename Hash,
29  typename Equal,
30  typename MemoryPolicy,
31  bits_t B>
32 struct node
33 {
34  using node_t = node;
35 
36  using memory = MemoryPolicy;
37  using heap_policy = typename memory::heap;
38  using heap = typename heap_policy::type;
39  using transience = typename memory::transience_t;
40  using refs_t = typename memory::refcount;
41  using ownee_t = typename transience::ownee;
42  using edit_t = typename transience::edit;
43  using value_t = T;
45 
46  enum class kind_t
47  {
48  collision,
49  inner
50  };
51 
52  struct collision_t
53  {
56  };
57 
59  {
61  };
62 
65 
66  struct inner_t
67  {
72  };
73 
74  union data_t
75  {
78  };
79 
80  struct impl_data_t
81  {
82 #if IMMER_HAMTS_TAGGED_NODE
84 #endif
86  };
87 
90 
92 
94  {
95  return immer_offsetof(values_t, d.buffer)
96  + sizeof(values_data_t::buffer) * count;
97  }
98 
100  {
101  return immer_offsetof(impl_t, d.data.collision.buffer)
102  + sizeof(collision_t::buffer) * count;
103  }
104 
106  {
107  return immer_offsetof(impl_t, d.data.inner.buffer)
108  + sizeof(inner_t::buffer) * count;
109  }
110 
111 #if IMMER_HAMTS_TAGGED_NODE
112  kind_t kind() const
113  {
114  return impl.d.kind;
115  }
116 #endif
117 
118  auto values()
119  {
120  assert(kind() == kind_t::inner);
121  assert(impl.d.data.inner.values);
122  return (T*) &impl.d.data.inner.values->d.buffer;
123  }
124 
125  auto values() const
126  {
127  assert(kind() == kind_t::inner);
128  assert(impl.d.data.inner.values);
129  return (const T*) &impl.d.data.inner.values->d.buffer;
130  }
131 
132  auto children()
133  {
134  assert(kind() == kind_t::inner);
135  return (node_t**) &impl.d.data.inner.buffer;
136  }
137 
138  auto children() const
139  {
140  assert(kind() == kind_t::inner);
141  return (const node_t* const*) &impl.d.data.inner.buffer;
142  }
143 
144  auto datamap() const
145  {
146  assert(kind() == kind_t::inner);
147  return impl.d.data.inner.datamap;
148  }
149 
150  auto nodemap() const
151  {
152  assert(kind() == kind_t::inner);
153  return impl.d.data.inner.nodemap;
154  }
155 
156  auto collision_count() const
157  {
158  assert(kind() == kind_t::collision);
159  return impl.d.data.collision.count;
160  }
161 
163  {
164  assert(kind() == kind_t::collision);
165  return (T*)&impl.d.data.collision.buffer;
166  }
167 
168  const T* collisions() const
169  {
170  assert(kind() == kind_t::collision);
171  return (const T*)&impl.d.data.collision.buffer;
172  }
173 
174  static refs_t& refs(const values_t* x) { return auto_const_cast(get<refs_t>(*x)); }
175  static const ownee_t& ownee(const values_t* x) { return get<ownee_t>(*x); }
176  static ownee_t& ownee(values_t* x) { return get<ownee_t>(*x); }
177 
178  static refs_t& refs(const node_t* x) { return auto_const_cast(get<refs_t>(x->impl)); }
179  static const ownee_t& ownee(const node_t* x) { return get<ownee_t>(x->impl); }
180  static ownee_t& ownee(node_t* x) { return get<ownee_t>(x->impl); }
181 
183  {
184  assert(n <= branches<B>);
185  auto m = heap::allocate(sizeof_inner_n(n));
186  auto p = new (m) node_t;
187 #if IMMER_HAMTS_TAGGED_NODE
188  p->impl.d.kind = node_t::kind_t::inner;
189 #endif
190  p->impl.d.data.inner.nodemap = 0;
191  p->impl.d.data.inner.datamap = 0;
192  p->impl.d.data.inner.values = nullptr;
193  return p;
194  }
195 
197  {
198  auto p = make_inner_n(n);
199  if (values) {
200  p->impl.d.data.inner.values = values;
201  refs(values).inc();
202  }
203  return p;
204  }
205 
207  {
208  assert(nv <= branches<B>);
209  auto p = make_inner_n(n);
210  if (nv) {
211  try {
212  p->impl.d.data.inner.values =
213  new (heap::allocate(sizeof_values_n(nv))) values_t{};
214  } catch (...) {
215  deallocate_inner(p, n);
216  throw;
217  }
218  }
219  return p;
220  }
221 
222  static node_t* make_inner_n(count_t n, count_t idx, node_t* child)
223  {
224  assert(n >= 1);
225  auto p = make_inner_n(n);
226  p->impl.d.data.inner.nodemap = bitmap_t{1u} << idx;
227  p->children()[0] = child;
228  return p;
229  }
230 
232  bitmap_t bitmap,
233  T x)
234  {
235  auto p = make_inner_n(n, 1);
236  p->impl.d.data.inner.datamap = bitmap;
237  try {
238  new (p->values()) T{std::move(x)};
239  } catch (...) {
240  deallocate_inner(p, n, 1);
241  throw;
242  }
243  return p;
244  }
245 
247  count_t idx1, T x1,
248  count_t idx2, T x2)
249  {
250  assert(idx1 != idx2);
251  auto p = make_inner_n(n, 2);
252  p->impl.d.data.inner.datamap = (bitmap_t{1u} << idx1) | (bitmap_t{1u} << idx2);
253  auto assign = [&] (auto&& x1, auto&& x2) {
254  auto vp = p->values();
255  try {
256  new (vp) T{std::move(x1)};
257  try {
258  new (vp + 1) T{std::move(x2)};
259  } catch (...) {
260  vp->~T();
261  throw;
262  }
263  } catch (...) {
264  deallocate_inner(p, n, 2);
265  throw;
266  }
267  };
268  if (idx1 < idx2)
269  assign(x1, x2);
270  else
271  assign(x2, x1);
272  return p;
273  }
274 
276  {
277  assert(n <= branches<B>);
278  auto m = heap::allocate(sizeof_collision_n(n));
279  auto p = new (m) node_t;
280 #if IMMER_HAMTS_TAGGED_NODE
281  p->impl.d.kind = node_t::kind_t::collision;
282 #endif
283  p->impl.d.data.collision.count = n;
284  return p;
285  }
286 
287  static node_t* make_collision(T v1, T v2)
288  {
289  auto m = heap::allocate(sizeof_collision_n(2));
290  auto p = new (m) node_t;
291 #if IMMER_HAMTS_TAGGED_NODE
292  p->impl.d.kind = node_t::kind_t::collision;
293 #endif
294  p->impl.d.data.collision.count = 2;
295  auto cols = p->collisions();
296  try {
297  new (cols) T{std::move(v1)};
298  try {
299  new (cols + 1) T{std::move(v2)};
300  } catch (...) {
301  cols->~T();
302  throw;
303  }
304  } catch (...) {
305  deallocate_collision(p, 2);
306  throw;
307  }
308  return p;
309  }
310 
312  {
313  assert(src->kind() == kind_t::collision);
314  auto n = src->collision_count();
315  auto dst = make_collision_n(n + 1);
316  auto srcp = src->collisions();
317  auto dstp = dst->collisions();
318  try {
319  new (dstp) T{std::move(v)};
320  try {
321  std::uninitialized_copy(srcp, srcp + n, dstp + 1);
322  } catch (...) {
323  dstp->~T();
324  throw;
325  }
326  } catch (...) {
327  deallocate_collision(dst, n + 1);
328  throw;
329  }
330  return dst;
331  }
332 
333  static node_t* copy_collision_remove(node_t* src, T* v)
334  {
335  assert(src->kind() == kind_t::collision);
336  assert(src->collision_count() > 1);
337  auto n = src->collision_count();
338  auto dst = make_collision_n(n - 1);
339  auto srcp = src->collisions();
340  auto dstp = dst->collisions();
341  try {
342  dstp = std::uninitialized_copy(srcp, v, dstp);
343  try {
344  std::uninitialized_copy(v + 1, srcp + n, dstp);
345  } catch (...) {
346  destroy(dst->collisions(), dstp);
347  throw;
348  }
349  } catch (...) {
350  deallocate_collision(dst, n - 1);
351  throw;
352  }
353  return dst;
354  }
355 
356  static node_t* copy_collision_replace(node_t* src, T* pos, T v)
357  {
358  assert(src->kind() == kind_t::collision);
359  auto n = src->collision_count();
360  auto dst = make_collision_n(n);
361  auto srcp = src->collisions();
362  auto dstp = dst->collisions();
363  assert(pos >= srcp && pos < srcp + n);
364  try {
365  new (dstp) T{std::move(v)};
366  try {
367  dstp = std::uninitialized_copy(srcp, pos, dstp + 1);
368  try {
369  std::uninitialized_copy(pos + 1, srcp + n, dstp);
370  } catch (...) {
371  destroy(dst->collisions(), dstp);
372  throw;
373  }
374  } catch (...) {
375  dst->collisions()->~T();
376  throw;
377  }
378  } catch (...) {
379  deallocate_collision(dst, n);
380  throw;
381  }
382  return dst;
383  }
384 
386  count_t offset, node_t* child)
387  {
388  assert(src->kind() == kind_t::inner);
389  auto n = popcount(src->nodemap());
390  auto dst = make_inner_n(n, src->impl.d.data.inner.values);
391  auto srcp = src->children();
392  auto dstp = dst->children();
393  dst->impl.d.data.inner.datamap = src->datamap();
394  dst->impl.d.data.inner.nodemap = src->nodemap();
395  std::uninitialized_copy(srcp, srcp + n, dstp);
396  inc_nodes(srcp, n);
397  srcp[offset]->dec_unsafe();
398  dstp[offset] = child;
399  return dst;
400  }
401 
403  count_t offset, T v)
404  {
405  assert(src->kind() == kind_t::inner);
406  assert(offset < popcount(src->datamap()));
407  auto n = popcount(src->nodemap());
408  auto nv = popcount(src->datamap());
409  auto dst = make_inner_n(n, nv);
410  dst->impl.d.data.inner.datamap = src->datamap();
411  dst->impl.d.data.inner.nodemap = src->nodemap();
412  try {
414  src->values(), src->values() + nv, dst->values());
415  try {
416  dst->values()[offset] = std::move(v);
417  } catch (...) {
418  destroy_n(dst->values(), nv);
419  throw;
420  }
421  } catch (...) {
422  deallocate_inner(dst, n, nv);
423  throw;
424  }
425  inc_nodes(src->children(), n);
427  src->children(), src->children() + n, dst->children());
428  return dst;
429  }
430 
432  node_t* src, bitmap_t bit, count_t voffset, node_t* node)
433  {
434  assert(src->kind() == kind_t::inner);
435  assert(!(src->nodemap() & bit));
436  assert(src->datamap() & bit);
437  assert(voffset == popcount(src->datamap() & (bit - 1)));
438  auto n = popcount(src->nodemap());
439  auto nv = popcount(src->datamap());
440  auto dst = make_inner_n(n + 1, nv - 1);
441  auto noffset = popcount(src->nodemap() & (bit - 1));
442  dst->impl.d.data.inner.datamap = src->datamap() & ~bit;
443  dst->impl.d.data.inner.nodemap = src->nodemap() | bit;
444  if (nv > 1) {
445  try {
447  src->values(), src->values() + voffset,
448  dst->values());
449  try {
451  src->values() + voffset + 1, src->values() + nv,
452  dst->values() + voffset);
453  } catch (...) {
454  destroy_n(dst->values(), voffset);
455  throw;
456  }
457  } catch (...) {
458  deallocate_inner(dst, n + 1, nv - 1);
459  throw;
460  }
461  }
462  inc_nodes(src->children(), n);
464  src->children(), src->children() + noffset,
465  dst->children());
467  src->children() + noffset, src->children() + n,
468  dst->children() + noffset + 1);
469  dst->children()[noffset] = node;
470  return dst;
471  }
472 
474  node_t* src, bitmap_t bit, count_t noffset, T value)
475  {
476  assert(src->kind() == kind_t::inner);
477  assert(!(src->datamap() & bit));
478  assert(src->nodemap() & bit);
479  assert(noffset == popcount(src->nodemap() & (bit - 1)));
480  auto n = popcount(src->nodemap());
481  auto nv = popcount(src->datamap());
482  auto dst = make_inner_n(n - 1, nv + 1);
483  auto voffset = popcount(src->datamap() & (bit - 1));
484  dst->impl.d.data.inner.nodemap = src->nodemap() & ~bit;
485  dst->impl.d.data.inner.datamap = src->datamap() | bit;
486  try {
487  if (nv)
489  src->values(), src->values() + voffset,
490  dst->values());
491  try {
492  new (dst->values() + voffset) T{std::move(value)};
493  try {
494  if (nv)
496  src->values() + voffset, src->values() + nv,
497  dst->values() + voffset + 1);
498  } catch (...) {
499  dst->values()[voffset].~T();
500  throw;
501  }
502  } catch (...) {
503  destroy_n(dst->values(), voffset);
504  throw;
505  }
506  } catch (...) {
507  deallocate_inner(dst, n - 1, nv + 1);
508  throw;
509  }
510  inc_nodes(src->children(), n);
511  src->children()[noffset]->dec_unsafe();
513  src->children(), src->children() + noffset,
514  dst->children());
516  src->children() + noffset + 1, src->children() + n,
517  dst->children() + noffset);
518  return dst;
519  }
520 
522  node_t* src, bitmap_t bit, count_t voffset)
523  {
524  assert(src->kind() == kind_t::inner);
525  assert(!(src->nodemap() & bit));
526  assert(src->datamap() & bit);
527  assert(voffset == popcount(src->datamap() & (bit - 1)));
528  auto n = popcount(src->nodemap());
529  auto nv = popcount(src->datamap());
530  auto dst = make_inner_n(n, nv - 1);
531  dst->impl.d.data.inner.datamap = src->datamap() & ~bit;
532  dst->impl.d.data.inner.nodemap = src->nodemap();
533  if (nv > 1) {
534  try {
536  src->values(), src->values() + voffset,
537  dst->values());
538  try {
540  src->values() + voffset + 1, src->values() + nv,
541  dst->values() + voffset);
542  } catch (...) {
543  destroy_n(dst->values(), voffset);
544  throw;
545  }
546  } catch (...) {
547  deallocate_inner(dst, n, nv - 1);
548  throw;
549  }
550  }
551  inc_nodes(src->children(), n);
553  src->children(), src->children() + n, dst->children());
554  return dst;
555  }
556 
558  {
559  assert(src->kind() == kind_t::inner);
560  auto n = popcount(src->nodemap());
561  auto nv = popcount(src->datamap());
562  auto offset = popcount(src->datamap() & (bit - 1));
563  auto dst = make_inner_n(n, nv + 1);
564  dst->impl.d.data.inner.datamap = src->datamap() | bit;
565  dst->impl.d.data.inner.nodemap = src->nodemap();
566  try {
567  if (nv)
569  src->values(), src->values() + offset, dst->values());
570  try {
571  new (dst->values() + offset) T{std::move(v)};
572  try {
573  if (nv)
575  src->values() + offset, src->values() + nv,
576  dst->values() + offset + 1);
577  } catch (...) {
578  dst->values()[offset].~T();
579  throw;
580  }
581  } catch (...) {
582  destroy_n(dst->values(), offset);
583  throw;
584  }
585  } catch (...) {
586  deallocate_inner(dst, n, nv + 1);
587  throw;
588  }
589  inc_nodes(src->children(), n);
591  src->children(), src->children() + n, dst->children());
592  return dst;
593  }
594 
595  static node_t* make_merged(shift_t shift,
596  T v1, hash_t hash1,
597  T v2, hash_t hash2)
598  {
599  if (shift < max_shift<B>) {
600  auto idx1 = hash1 & (mask<B> << shift);
601  auto idx2 = hash2 & (mask<B> << shift);
602  if (idx1 == idx2) {
603  auto merged = make_merged(shift + B,
604  std::move(v1), hash1,
605  std::move(v2), hash2);
606  try {
607  return make_inner_n(1, idx1 >> shift, merged);
608  } catch (...) {
609  delete_deep_shift(merged, shift + B);
610  throw;
611  }
612  } else {
613  return make_inner_n(0,
614  idx1 >> shift, std::move(v1),
615  idx2 >> shift, std::move(v2));
616  }
617  } else {
618  return make_collision(std::move(v1), std::move(v2));
619  }
620  }
621 
623  {
624  refs(this).inc();
625  return this;
626  }
627 
628  const node_t* inc() const
629  {
630  refs(this).inc();
631  return this;
632  }
633 
634  bool dec() const { return refs(this).dec(); }
635  void dec_unsafe() const { refs(this).dec_unsafe(); }
636 
637  static void inc_nodes(node_t** p, count_t n)
638  {
639  for (auto i = p, e = i + n; i != e; ++i)
640  refs(*i).inc();
641  }
642 
643  static void delete_values(values_t* p, count_t n)
644  {
645  assert(p);
646  deallocate_values(p, n);
647  }
648 
649  static void delete_inner(node_t* p)
650  {
651  assert(p);
652  assert(p->kind() == kind_t::inner);
653  auto vp = p->impl.d.data.inner.values;
654  if (vp && refs(vp).dec())
655  delete_values(vp, popcount(p->datamap()));
657  }
658 
659  static void delete_collision(node_t* p)
660  {
661  assert(p);
662  assert(p->kind() == kind_t::collision);
663  auto n = p->collision_count();
664  deallocate_collision(p, n);
665  }
666 
667  static void delete_deep(node_t* p, shift_t s)
668  {
669  if (s == max_depth<B>)
670  delete_collision(p);
671  else {
672  auto fst = p->children();
673  auto lst = fst + popcount(p->nodemap());
674  for (; fst != lst; ++fst)
675  if ((*fst)->dec())
676  delete_deep(*fst, s + 1);
677  delete_inner(p);
678  }
679  }
680 
681  static void delete_deep_shift(node_t* p, shift_t s)
682  {
683  if (s == max_shift<B>)
684  delete_collision(p);
685  else {
686  auto fst = p->children();
687  auto lst = fst + popcount(p->nodemap());
688  for (; fst != lst; ++fst)
689  if ((*fst)->dec())
690  delete_deep_shift(*fst, s + B);
691  delete_inner(p);
692  }
693  }
694 
695  static void deallocate_values(values_t* p, count_t n)
696  {
697  destroy_n((T*) &p->d.buffer, n);
698  heap::deallocate(node_t::sizeof_values_n(n), p);
699  }
700 
702  {
703  destroy_n(p->collisions(), n);
704  heap::deallocate(node_t::sizeof_collision_n(n), p);
705  }
706 
707  static void deallocate_inner(node_t* p, count_t n)
708  {
709  heap::deallocate(node_t::sizeof_inner_n(n), p);
710  }
711 
712  static void deallocate_inner(node_t* p, count_t n, count_t nv)
713  {
714  assert(nv);
715  heap::deallocate(node_t::sizeof_values_n(nv), p->impl.d.data.inner.values);
716  heap::deallocate(node_t::sizeof_inner_n(n), p);
717  }
718 };
719 
720 } // namespace hamts
721 } // namespace detail
722 } // namespace immer
void destroy(T *first, T *last)
Definition: util.hpp:45
static refs_t & refs(const values_t *x)
Definition: node.hpp:174
auto values() const
Definition: node.hpp:125
std::uint32_t count_t
Definition: bits.hpp:24
static node_t * make_inner_n(count_t n, bitmap_t bitmap, T x)
Definition: node.hpp:231
#define immer_offsetof
static void inc_nodes(node_t **p, count_t n)
Definition: node.hpp:637
void destroy_n(T *p, Size n)
Definition: util.hpp:52
static ownee_t & ownee(values_t *x)
Definition: node.hpp:176
static node_t * copy_collision_remove(node_t *src, T *v)
Definition: node.hpp:333
static void delete_deep_shift(node_t *p, shift_t s)
Definition: node.hpp:681
MemoryPolicy memory
Definition: node.hpp:36
std::uint32_t shift_t
Definition: bits.hpp:25
static node_t * make_inner_n(count_t n, count_t idx1, T x1, count_t idx2, T x2)
Definition: node.hpp:246
static node_t * copy_inner_insert_value(node_t *src, bitmap_t bit, T v)
Definition: node.hpp:557
static ownee_t & ownee(node_t *x)
Definition: node.hpp:180
auto children() const
Definition: node.hpp:138
auto nodemap() const
Definition: node.hpp:150
typename get_bitmap_type< B >::type bitmap_t
Definition: node.hpp:44
static node_t * make_collision_n(count_t n)
Definition: node.hpp:275
static void deallocate_collision(node_t *p, count_t n)
Definition: node.hpp:701
static node_t * copy_collision_replace(node_t *src, T *pos, T v)
Definition: node.hpp:356
auto collision_count() const
Definition: node.hpp:156
typename heap_policy::type heap
Definition: node.hpp:38
static const ownee_t & ownee(const values_t *x)
Definition: node.hpp:175
static const ownee_t & ownee(const node_t *x)
Definition: node.hpp:179
static void delete_values(values_t *p, count_t n)
Definition: node.hpp:643
typename memory::heap heap_policy
Definition: node.hpp:37
static node_t * make_merged(shift_t shift, T v1, hash_t hash1, T v2, hash_t hash2)
Definition: node.hpp:595
static node_t * make_inner_n(count_t n)
Definition: node.hpp:182
SinkIter uninitialized_copy(Iterator first, Sentinel last, SinkIter d_first)
Definition: util.hpp:192
static constexpr std::size_t sizeof_values_n(count_t count)
Definition: node.hpp:93
std::uint32_t bits_t
Definition: bits.hpp:23
static void deallocate_inner(node_t *p, count_t n, count_t nv)
Definition: node.hpp:712
auto datamap() const
Definition: node.hpp:144
std::size_t size_t
Definition: bits.hpp:21
typename memory::transience_t transience
Definition: node.hpp:39
kind_t kind() const
Definition: node.hpp:112
static void delete_inner(node_t *p)
Definition: node.hpp:649
static node_t * copy_inner_remove_value(node_t *src, bitmap_t bit, count_t voffset)
Definition: node.hpp:521
aligned_storage_for< T > buffer
Definition: node.hpp:60
typename transience::edit edit_t
Definition: node.hpp:42
void dec_unsafe() const
Definition: node.hpp:635
static node_t * make_inner_n(count_t n, count_t nv)
Definition: node.hpp:206
static node_t * copy_inner_replace_merged(node_t *src, bitmap_t bit, count_t voffset, node_t *node)
Definition: node.hpp:431
static node_t * make_inner_n(count_t n, count_t idx, node_t *child)
Definition: node.hpp:222
static void deallocate_values(values_t *p, count_t n)
Definition: node.hpp:695
count_t popcount(std::uint32_t x)
Definition: bits.hpp:73
uint256 Hash(const T1 pbegin, const T1 pend)
Compute the 256-bit hash of an object.
Definition: hash.h:84
std::size_t hash_t
Definition: bits.hpp:22
combine_standard_layout_t< values_data_t, refs_t > values_t
Definition: node.hpp:64
aligned_storage_for< node_t * > buffer
Definition: node.hpp:71
static refs_t & refs(const node_t *x)
Definition: node.hpp:178
static void delete_collision(node_t *p)
Definition: node.hpp:659
static void delete_deep(node_t *p, shift_t s)
Definition: node.hpp:667
static node_t * make_collision(T v1, T v2)
Definition: node.hpp:287
aligned_storage_for< T > buffer
Definition: node.hpp:55
typename combine_standard_layout< Ts... >::type combine_standard_layout_t
typename transience::ownee ownee_t
Definition: node.hpp:41
static void deallocate_inner(node_t *p, count_t n)
Definition: node.hpp:707
typename memory::refcount refs_t
Definition: node.hpp:40
T & auto_const_cast(const T &x)
Definition: util.hpp:32
static int count
Definition: tests.c:45
typename std::aligned_storage< sizeof(T), alignof(T)>::type aligned_storage_for
Definition: util.hpp:29
const node_t * inc() const
Definition: node.hpp:628
static node_t * make_inner_n(count_t n, values_t *values)
Definition: node.hpp:196
combine_standard_layout_t< impl_data_t, refs_t > impl_t
Definition: node.hpp:89
static constexpr std::size_t sizeof_collision_n(count_t count)
Definition: node.hpp:99
static node_t * copy_inner_replace_value(node_t *src, count_t offset, T v)
Definition: node.hpp:402
static node_t * copy_collision_insert(node_t *src, T v)
Definition: node.hpp:311
static node_t * copy_inner_replace_inline(node_t *src, bitmap_t bit, count_t noffset, T value)
Definition: node.hpp:473
static node_t * copy_inner_replace(node_t *src, count_t offset, node_t *child)
Definition: node.hpp:385
const T * collisions() const
Definition: node.hpp:168
static constexpr std::size_t sizeof_inner_n(count_t count)
Definition: node.hpp:105
Released under the MIT license