Cuberite
A lightweight, fast and extensible game server for Minecraft
LazyArray.h
Go to the documentation of this file.
1 
2 #pragma once
3 
7 template <typename T>
8 class cLazyArray
9 {
10  static_assert((!std::is_reference<T>::value && !std::is_array<T>::value),
11  "cLazyArray<T>: T must be a value type");
12  static_assert(std::is_default_constructible<T>::value,
13  "cLazyArray<T>: T must be default constructible");
14 public:
15  using value_type = T;
16  using pointer = T *;
17  using const_pointer = const T *;
18  using reference = T &;
19  using const_reference = const T &;
20  using size_type = int;
21  using iterator = pointer;
23 
24  cLazyArray(size_type a_Size) noexcept:
25  m_Size{ a_Size }
26  {
27  ASSERT(a_Size > 0);
28  }
29 
30  cLazyArray(const cLazyArray & a_Other):
31  m_Size{ a_Other.m_Size }
32  {
33  if (a_Other.IsStorageAllocated())
34  {
35  // Note that begin() will allocate the array to copy into
36  std::copy(a_Other.begin(), a_Other.end(), begin());
37  }
38  }
39 
40  cLazyArray(cLazyArray && a_Other) noexcept:
41  m_Array{ std::move(a_Other.m_Array) },
42  m_Size{ a_Other.m_Size }
43  {
44  }
45 
46  cLazyArray & operator = (const cLazyArray & a_Other)
47  {
48  cLazyArray(a_Other).swap(*this);
49  return *this;
50  }
51 
52  cLazyArray & operator = (cLazyArray && a_Other) noexcept
53  {
54  m_Array = std::move(a_Other.m_Array);
55  m_Size = a_Other.m_Size;
56  return *this;
57  }
58 
60  {
61  ASSERT((0 <= a_Idx) && (a_Idx < m_Size));
62  return data()[a_Idx];
63  }
64 
65  const T & operator [] (size_type a_Idx) const
66  {
67  return GetAt(a_Idx);
68  }
69 
70  // STL style interface
71 
72  const_iterator cbegin() const { return data(); }
73  iterator begin() { return data(); }
74  const_iterator begin() const { return cbegin(); }
75 
76  const_iterator cend() const { return data() + m_Size; }
77  iterator end() { return data() + m_Size; }
78  const_iterator end() const { return cend(); }
79 
80  size_type size() const noexcept { return m_Size; }
81 
82  const T * data() const
83  {
84  if (m_Array == nullptr)
85  {
86  m_Array.reset(new T[ToUnsigned(m_Size)]);
87  }
88  return m_Array.get();
89  }
90 
91  T * data()
92  {
93  static_assert(!std::is_const<typename decltype(m_Array)::element_type>::value, "");
94  const cLazyArray * const_this = this;
95  return const_cast<T *>(const_this->data());
96  }
97 
98  void swap(cLazyArray & a_Other) noexcept
99  {
100  std::swap(m_Array, a_Other.m_Array);
101  std::swap(m_Size, a_Other.m_Size);
102  }
103 
104  friend void swap(cLazyArray & a_Lhs, cLazyArray & a_Rhs) noexcept
105  {
106  a_Lhs.swap(a_Rhs);
107  }
108 
109  // Extra functions to help avoid allocation
110 
112  const T & GetAt(size_type a_Idx) const
113  {
114  ASSERT((0 <= a_Idx) && (a_Idx < m_Size));
115  if (IsStorageAllocated())
116  {
117  return data()[a_Idx];
118  }
119  else
120  {
121  static const T DefaultValue;
122  return DefaultValue;
123  }
124  }
125 
127  bool IsStorageAllocated() const noexcept { return (m_Array != nullptr); }
128 
129 private:
130  // Mutable so const data() can allocate the array
131  mutable std::unique_ptr<T[]> m_Array;
133 };
134 
auto ToUnsigned(T a_Val)
Definition: Globals.h:387
#define ASSERT(x)
Definition: Globals.h:276
A dynamic array that defers allocation to the first modifying access.
Definition: LazyArray.h:9
friend void swap(cLazyArray &a_Lhs, cLazyArray &a_Rhs) noexcept
Definition: LazyArray.h:104
iterator end()
Definition: LazyArray.h:77
const T & const_reference
Definition: LazyArray.h:19
T & reference
Definition: LazyArray.h:18
const_iterator cbegin() const
Definition: LazyArray.h:72
const_iterator end() const
Definition: LazyArray.h:78
T * pointer
Definition: LazyArray.h:16
bool IsStorageAllocated() const noexcept
Returns true if the array has already been allocated.
Definition: LazyArray.h:127
const_iterator cend() const
Definition: LazyArray.h:76
int size_type
Definition: LazyArray.h:20
void swap(cLazyArray &a_Other) noexcept
Definition: LazyArray.h:98
T & operator[](size_type a_Idx)
Definition: LazyArray.h:59
cLazyArray(const cLazyArray &a_Other)
Definition: LazyArray.h:30
T value_type
Definition: LazyArray.h:15
cLazyArray(cLazyArray &&a_Other) noexcept
Definition: LazyArray.h:40
const T * data() const
Definition: LazyArray.h:82
const T & GetAt(size_type a_Idx) const
A const view of an element of the array.
Definition: LazyArray.h:112
T * data()
Definition: LazyArray.h:91
size_type m_Size
Definition: LazyArray.h:132
pointer iterator
Definition: LazyArray.h:21
cLazyArray & operator=(const cLazyArray &a_Other)
Definition: LazyArray.h:46
iterator begin()
Definition: LazyArray.h:73
const T * const_pointer
Definition: LazyArray.h:17
cLazyArray(size_type a_Size) noexcept
Definition: LazyArray.h:24
const_pointer const_iterator
Definition: LazyArray.h:22
const_iterator begin() const
Definition: LazyArray.h:74
size_type size() const noexcept
Definition: LazyArray.h:80
std::unique_ptr< T[]> m_Array
Definition: LazyArray.h:131