| 203 | |
| 204 | template <typename Element, size_t MaxStackSize> |
| 205 | void SmallVector<Element, MaxStackSize>::reserve(size_t newCapacity) { |
| 206 | size_t oldCapacity = m_capacity - m_begin; |
| 207 | if (newCapacity > oldCapacity) { |
| 208 | newCapacity = max(oldCapacity * 2, newCapacity); |
| 209 | auto newMem = (Element*)Star::malloc(newCapacity * sizeof(Element)); |
| 210 | if (!newMem) |
| 211 | throw MemoryException::format("Could not set new SmallVector capacity {}\n", newCapacity); |
| 212 | |
| 213 | size_t size = m_end - m_begin; |
| 214 | auto oldMem = m_begin; |
| 215 | auto oldHeapAllocated = isHeapAllocated(); |
| 216 | |
| 217 | // We assume that move constructors can never throw. |
| 218 | for (size_t i = 0; i < size; ++i) { |
| 219 | new (&newMem[i]) Element(std::move(oldMem[i])); |
| 220 | } |
| 221 | |
| 222 | m_begin = newMem; |
| 223 | m_end = m_begin + size; |
| 224 | m_capacity = m_begin + newCapacity; |
| 225 | |
| 226 | auto freeOldMem = finally([=]() { |
| 227 | if (oldHeapAllocated) |
| 228 | Star::free(oldMem, oldCapacity * sizeof(Element)); |
| 229 | }); |
| 230 | |
| 231 | for (size_t i = 0; i < size; ++i) { |
| 232 | oldMem[i].~Element(); |
| 233 | } |
| 234 | } |
| 235 | } |
| 236 | |
| 237 | template <typename Element, size_t MaxStackSize> |
| 238 | auto SmallVector<Element, MaxStackSize>::at(size_t i) -> reference { |