1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
|
#pragma once
#include <iostream>
#include <vector>
#include <limits>
#include <cassert>
using index_t = std::size_t;
static constexpr std::size_t invalid_index = std::numeric_limits<index_t>::max();
struct IndexWrapper {
index_t objectID;
};
template<typename ObjectType>
struct ObjectWrapper: public IndexWrapper, public ObjectType
{
template<typename ...Args>
explicit ObjectWrapper(index_t const id, Args... args): IndexWrapper{id}, ObjectType{args...} {}
ObjectWrapper(): IndexWrapper{invalid_index} {}
};
template<typename ObjectType>
class ObjectPool
{
using data_t = ObjectWrapper<ObjectType>;
private:
std::vector<data_t> mData;
std::vector<size_t> mIndex;
size_t indexOf(index_t const objectID) {
assert(exist(objectID));
return mIndex[objectID];
}
public:
explicit ObjectPool(size_t const cap) {
mData.reserve(cap);
mIndex.resize(cap, invalid_index);
}
~ObjectPool() = default;
bool exist(index_t const objectID) {
return mIndex[objectID] != invalid_index;
}
data_t & operator[](index_t const objectID) {
return mData[indexOf(objectID)];
}
data_t const & operator[](index_t const objectID) const {
return const_cast<data_t&>(mData[indexOf(objectID)]);
}
data_t & get(index_t const objectID) {
return mData[indexOf(objectID)];
}
data_t const & get(index_t const objectID) const {
return const_cast<data_t&>(mData[indexOf(objectID)]);
}
template<typename ...Args>
void push(index_t const objectID, Args... args) {
mData.push_back(data_t{objectID, args...});
mIndex[objectID] = size();
}
void pop(index_t const objectID) {
assert(exist(objectID));
index_t tempID{mData[size()-1].objectID};
std::swap(mData[indexOf(objectID)], mData[size()-1]);
mIndex[tempID] = indexOf(objectID);
mIndex[objectID] = invalid_index;
mData.resize(size()-1);
}
class iterator
{
private:
std::vector<data_t> & mCurrent;
size_t mCursor{0};
size_t mRange{0};
public:
iterator(ObjectPool<ObjectType> & src):
mCurrent{src.mData},
mCursor{0},
mRange{src.size()}
{
}
iterator(ObjectPool<ObjectType> & src, size_t const offset):
mCurrent{src.mData},
mCursor{offset},
mRange{src.size()}
{
}
~iterator() = default;
void operator++() {
if(mRange != mCurrent.size()) {
mRange = mCurrent.size();
} else {
++mCursor;
}
}
bool operator!=(iterator const & src) const {
return mCursor != (src.mCursor - (src.mRange - mRange));
}
data_t & operator*() {
return mCurrent[mCursor];
}
};
size_t size() {
return mData.size();
}
iterator begin() {
iterator it(*this);
return it;
}
iterator end() {
iterator it(*this, size());
return it;
}
};
struct val{
uint32_t value{0};
};
int main() {
ObjectPool<val> mVal(6);
for(size_t i{0}; i < 6; ++i) {
mVal.push(i, i);
}
std::cout << "mVal size : " << mVal.size() << '\n';
for(auto & v:mVal) {
if(v.value % 2) {
std::cout << "delete : " << v.objectID << '\n';
mVal.pop(v.objectID);
} else {
std::cout << v.objectID << ':';
std::cout << v.value << '\n';
}
}
return 0;
} |
Partager