Photon Engine 2.0.0-beta
A physically based renderer.
Loading...
Searching...
No Matches
TUniquePtrVector.h
Go to the documentation of this file.
1#pragma once
2
3#include "Utility/IMoveOnly.h"
4
5#include <Common/assertion.h>
6
7#include <vector>
8#include <memory>
9#include <utility>
10#include <cstddef>
11#include <algorithm>
12#include <optional>
13#include <iterator>
14
15namespace ph
16{
17
18template<typename BaseType>
19class TUniquePtrVector final : private IMoveOnly
20{
21public:
22 // TODO: emplace
23
24 template<typename T>
25 T* add(std::unique_ptr<T> uniquePtr);
26
27 template<typename T>
28 void addAll(TUniquePtrVector<T>& uniquePtrs);
29
30 std::unique_ptr<BaseType> remove(std::size_t index);
31 std::unique_ptr<BaseType> remove(const BaseType* ptr);
32 std::unique_ptr<BaseType> removeLast();
33
38 std::unique_ptr<BaseType> removeBySwapPop(const BaseType* ptr);
39
40 void removeAll();
41 void clear(std::size_t index);
42
45 void clearRange(std::size_t beginIndex, std::size_t endIndex);
46
47 BaseType* get(std::size_t index) const;
48 BaseType* first() const;
49 BaseType* last() const;
50
51 std::unique_ptr<BaseType>& getUniquePtr(std::size_t index);
52 const std::unique_ptr<BaseType>& getUniquePtr(std::size_t index) const;
53
54 std::size_t size() const;
55 std::optional<std::size_t> indexOf(const BaseType* ptr) const;
56 bool isEmpty() const;
57
58 BaseType* operator [] (std::size_t index) const;
59
65 typename std::vector<std::unique_ptr<BaseType>>::iterator begin() noexcept;
66 typename std::vector<std::unique_ptr<BaseType>>::const_iterator begin() const noexcept;
67 typename std::vector<std::unique_ptr<BaseType>>::iterator end() noexcept;
68 typename std::vector<std::unique_ptr<BaseType>>::const_iterator end() const noexcept;
70
71private:
72 std::vector<std::unique_ptr<BaseType>> m_uniquePtrs;
73};
74
75// In-header Implementations:
76
77template<typename BaseType>
78template<typename T>
79inline T* TUniquePtrVector<BaseType>::add(std::unique_ptr<T> uniquePtr)
80{
81 // The `is_same` check is necessary since `is_base_of` would be false if `T` is a fundamental type
82 static_assert(std::is_base_of_v<BaseType, T> || std::is_same_v<BaseType, T>,
83 "The type of `unique_ptr` is not compatible to the vector.");
84
85 T* const ptr = uniquePtr.get();
86 m_uniquePtrs.push_back(std::move(uniquePtr));
87 return ptr;
88}
89
90template<typename BaseType>
91template<typename T>
93{
94 // The `is_same` check is necessary since `is_base_of` would be false if `T` is a fundamental type
95 static_assert(std::is_base_of_v<BaseType, T> || std::is_same_v<BaseType, T>,
96 "The type of `unique_ptr` is not compatible to the vector.");
97
98 m_uniquePtrs.insert(
99 m_uniquePtrs.end(),
100 std::make_move_iterator(uniquePtrs.begin()),
101 std::make_move_iterator(uniquePtrs.end()));
102
103 uniquePtrs.removeAll();
104}
105
106template<typename BaseType>
107inline std::unique_ptr<BaseType> TUniquePtrVector<BaseType>::remove(const std::size_t index)
108{
109 PH_ASSERT_IN_RANGE(index, 0, m_uniquePtrs.size());
110
111 auto uniquePtr = std::move(m_uniquePtrs[index]);
112 m_uniquePtrs.erase(m_uniquePtrs.begin() + index);
113 return uniquePtr;
114}
115
116template<typename BaseType>
117inline std::unique_ptr<BaseType> TUniquePtrVector<BaseType>::remove(const BaseType* const ptr)
118{
119 const auto optIndex = indexOf(ptr);
120 return optIndex ? remove(*optIndex) : nullptr;
121}
122
123template<typename BaseType>
124inline std::unique_ptr<BaseType> TUniquePtrVector<BaseType>::removeLast()
125{
126 PH_ASSERT(!isEmpty());
127
128 auto uniquePtr = std::move(m_uniquePtrs.back());
129 m_uniquePtrs.pop_back();
130 return uniquePtr;
131}
132
133template<typename BaseType>
134inline std::unique_ptr<BaseType> TUniquePtrVector<BaseType>::removeBySwapPop(const BaseType* const ptr)
135{
136 const auto optIndex = indexOf(ptr);
137 if(optIndex)
138 {
139 using std::swap;
140
141 swap(m_uniquePtrs[*optIndex], m_uniquePtrs.back());
142 m_uniquePtrs.pop_back();
143 }
144 else
145 {
146 return nullptr;
147 }
148}
149
150template<typename BaseType>
152{
153 m_uniquePtrs.clear();
154}
155
156template<typename BaseType>
157inline void TUniquePtrVector<BaseType>::clear(const std::size_t index)
158{
159 PH_ASSERT_IN_RANGE(index, 0, m_uniquePtrs.size());
160
161 m_uniquePtrs[index] = nullptr;
162}
163
164template<typename BaseType>
165inline void TUniquePtrVector<BaseType>::clearRange(const std::size_t beginIndex, const std::size_t endIndex)
166{
167 PH_ASSERT_LE(beginIndex, endIndex);
168
169 for(std::size_t ptrIndex = beginIndex; ptrIndex < endIndex; ++ptrIndex)
170 {
171 clear(ptrIndex);
172 }
173}
174
175template<typename BaseType>
176inline BaseType* TUniquePtrVector<BaseType>::get(const std::size_t index) const
177{
178 return index < m_uniquePtrs.size() ? getUniquePtr(index).get() : nullptr;
179}
180
181template<typename BaseType>
182inline BaseType* TUniquePtrVector<BaseType>::first() const
183{
184 PH_ASSERT(!isEmpty());
185 return m_uniquePtrs[0].get();
186}
187
188template<typename BaseType>
189inline BaseType* TUniquePtrVector<BaseType>::last() const
190{
191 PH_ASSERT(!isEmpty());
192 return m_uniquePtrs[size() - 1].get();
193}
194
195template<typename BaseType>
196inline std::optional<std::size_t> TUniquePtrVector<BaseType>::indexOf(const BaseType* const ptr) const
197{
198 const auto result = std::find_if(m_uniquePtrs.cbegin(), m_uniquePtrs.cend(),
199 [ptr](const std::unique_ptr<BaseType>& uniquePtr)
200 {
201 return ptr == uniquePtr.get();
202 });
203
204 return result != m_uniquePtrs.cend()
205 ? std::optional<std::size_t>(result - m_uniquePtrs.cbegin())
206 : std::nullopt;
207}
208
209template<typename BaseType>
210inline std::unique_ptr<BaseType>& TUniquePtrVector<BaseType>::getUniquePtr(const std::size_t index)
211{
212 PH_ASSERT_IN_RANGE(index, 0, m_uniquePtrs.size());
213 return m_uniquePtrs[index];
214}
215
216template<typename BaseType>
217inline const std::unique_ptr<BaseType>& TUniquePtrVector<BaseType>::getUniquePtr(const std::size_t index) const
218{
219 PH_ASSERT_IN_RANGE(index, 0, m_uniquePtrs.size());
220 return m_uniquePtrs[index];
221}
222
223template<typename BaseType>
224inline std::size_t TUniquePtrVector<BaseType>::size() const
225{
226 return m_uniquePtrs.size();
227}
228
229template<typename BaseType>
231{
232 return size() == 0;
233}
234
235template<typename BaseType>
236inline BaseType* TUniquePtrVector<BaseType>::operator [] (const std::size_t index) const
237{
238 return getUniquePtr(index).get();
239}
240
241template<typename BaseType>
242inline typename std::vector<std::unique_ptr<BaseType>>::iterator TUniquePtrVector<BaseType>::begin() noexcept
243{
244 return m_uniquePtrs.begin();
245}
246
247template<typename BaseType>
248inline typename std::vector<std::unique_ptr<BaseType>>::const_iterator TUniquePtrVector<BaseType>::begin() const noexcept
249{
250 return m_uniquePtrs.begin();
251}
252
253template<typename BaseType>
254inline typename std::vector<std::unique_ptr<BaseType>>::iterator TUniquePtrVector<BaseType>::end() noexcept
255{
256 return m_uniquePtrs.end();
257}
258
259template<typename BaseType>
260inline typename std::vector<std::unique_ptr<BaseType>>::const_iterator TUniquePtrVector<BaseType>::end() const noexcept
261{
262 return m_uniquePtrs.end();
263}
264
265}// end namespace ph
Marks the derived class as move only.
Definition IMoveOnly.h:23
Definition TUniquePtrVector.h:20
void clear(std::size_t index)
Definition TUniquePtrVector.h:157
std::unique_ptr< BaseType > remove(std::size_t index)
Definition TUniquePtrVector.h:107
BaseType * first() const
Definition TUniquePtrVector.h:182
void removeAll()
Definition TUniquePtrVector.h:151
BaseType * last() const
Definition TUniquePtrVector.h:189
void clearRange(std::size_t beginIndex, std::size_t endIndex)
Set unique_ptrs in the range [beginIndex, endIndex) to nullptr.
Definition TUniquePtrVector.h:165
BaseType * operator[](std::size_t index) const
Definition TUniquePtrVector.h:236
std::unique_ptr< BaseType > removeLast()
Definition TUniquePtrVector.h:124
std::unique_ptr< BaseType > & getUniquePtr(std::size_t index)
Definition TUniquePtrVector.h:210
std::optional< std::size_t > indexOf(const BaseType *ptr) const
Definition TUniquePtrVector.h:196
T * add(std::unique_ptr< T > uniquePtr)
Definition TUniquePtrVector.h:79
void addAll(TUniquePtrVector< T > &uniquePtrs)
Definition TUniquePtrVector.h:92
std::vector< std::unique_ptr< BaseType > >::iterator begin() noexcept
Definition TUniquePtrVector.h:242
std::vector< std::unique_ptr< BaseType > >::iterator end() noexcept
Definition TUniquePtrVector.h:254
std::unique_ptr< BaseType > removeBySwapPop(const BaseType *ptr)
Remove a unique_ptr. Does not preserve the order of remaining unique_ptrs. Complexity: O(N) where N i...
Definition TUniquePtrVector.h:134
bool isEmpty() const
Definition TUniquePtrVector.h:230
std::size_t size() const
Definition TUniquePtrVector.h:224
BaseType * get(std::size_t index) const
Definition TUniquePtrVector.h:176
The root for all renderer implementations.
Definition EEngineProject.h:6