49 static_assert(N > 0,
"SmallVector requires at least 1 inline element. Use std::vector for N=0.");
50 static_assert(N < 65536,
"SmallVector inline capacity is too large. Use std::vector instead.");
54 using size_type = size_t;
55 using difference_type = std::ptrdiff_t;
57 using const_reference =
const T&;
59 using const_pointer =
const T*;
61 using const_iterator =
const T*;
93 ensureCapacity(init.size());
94 for (
const auto& v : init) {
101 ensureCapacity(other.rawSize());
102 for (
const auto& v : other) {
109 if (other.isInline()) {
110 for (size_type i = 0; i < other.rawSize(); ++i) {
111 new (inlineData() + i) T(std::move(other.inlineData()[i]));
112 other.inlineData()[i].~T();
115 storage_.heap_.ptr = other.storage_.heap_.ptr;
116 storage_.heap_.capacity = other.storage_.heap_.capacity;
119 size_ = (size_ & kHeapBit) | other.rawSize();
129 if (
this != &other) {
132 ensureCapacity(other.rawSize());
133 for (
const auto& v : other) {
142 if (
this != &other) {
146 if (other.isInline()) {
147 for (size_type i = 0; i < other.rawSize(); ++i) {
148 new (inlineData() + i) T(std::move(other.inlineData()[i]));
149 other.inlineData()[i].~T();
152 storage_.heap_.ptr = other.storage_.heap_.ptr;
153 storage_.heap_.capacity = other.storage_.heap_.capacity;
156 size_ = (size_ & kHeapBit) | other.rawSize();
165 reference operator[](size_type pos) {
169 const_reference operator[](size_type pos)
const {
182 return data()[rawSize() - 1];
186 return data()[rawSize() - 1];
191 return isInline() ? inlineData() : storage_.heap_.ptr;
194 const_pointer
data() const noexcept {
195 return isInline() ? inlineData() : storage_.heap_.ptr;
205 const_iterator
begin() const noexcept {
214 return data() + rawSize();
217 const_iterator
end() const noexcept {
218 return data() + rawSize();
221 const_iterator
cend() const noexcept {
222 return data() + rawSize();
229 return rawSize() == 0;
232 size_type
size() const noexcept {
241 return isInline() ? N : storage_.heap_.capacity;
250 ensureCapacity(newCap);
279 template <
typename... Args>
283 size_type sz = rawSize();
288 ptr = storage_.heap_.ptr;
291 size_type sz = rawSize();
292 if (sz == storage_.heap_.capacity) {
293 growToHeap(storage_.heap_.capacity * 2);
295 ptr = storage_.heap_.ptr;
297 size_type idx = rawSize();
298 new (ptr + idx) T(std::forward<Args>(args)...);
301 assert(rawSize() > 0 &&
"Size overflow into heap bit");
308 size_type sz = rawSize();
320 size_type sz = rawSize();
322 ensureCapacity(count);
324 for (size_type i = sz; i < count; ++i) {
328 }
else if (count < sz) {
330 for (size_type i = count; i < sz; ++i) {
344 void resize(size_type count,
const T& value) {
345 size_type sz = rawSize();
347 ensureCapacity(count);
349 for (size_type i = sz; i < count; ++i) {
350 new (ptr + i) T(value);
353 }
else if (count < sz) {
355 for (size_type i = count; i < sz; ++i) {
370 iterator
erase(const_iterator pos) {
372 size_type sz = rawSize();
373 size_type index = pos - ptr;
375 for (size_type i = index; i + 1 < sz; ++i) {
376 ptr[i] = std::move(ptr[i + 1]);
380 return data() + index;
388 static constexpr size_type kHeapBit = size_type(1) << (
sizeof(size_type) * 8 - 1);
389 static constexpr size_type kSizeMask = ~kHeapBit;
391 bool isInline() const noexcept {
392 return (size_ & kHeapBit) == 0;
395 size_type rawSize() const noexcept {
396 return size_ & kSizeMask;
400 void setSize(size_type s)
noexcept {
401 assert((s & kHeapBit) == 0 &&
"Size overflow into heap bit");
402 size_ = (size_ & kHeapBit) | s;
405 T* inlineData() noexcept {
406 return reinterpret_cast<T*
>(&storage_.inline_);
408 const T* inlineData() const noexcept {
409 return reinterpret_cast<const T*
>(&storage_.inline_);
412 void destroyAll() noexcept {
414 size_type sz = rawSize();
415 for (size_type i = 0; i < sz; ++i) {
419 ::operator
delete(storage_.heap_.ptr);
425 void growToHeap(size_type newCap) {
426 T* newData =
static_cast<T*
>(::operator
new(newCap *
sizeof(T)));
428 size_type sz = rawSize();
430 for (size_type i = 0; i < sz; ++i) {
431 new (newData + i) T(std::move(oldData[i]));
436 ::operator
delete(storage_.heap_.ptr);
439 storage_.heap_.ptr = newData;
440 storage_.heap_.capacity = newCap;
441 size_ = kHeapBit | sz;
444 void ensureCapacity(size_type newCap) {
445 if (newCap <= N && isInline()) {
450 }
else if (newCap > storage_.heap_.capacity) {
463 alignas(T)
unsigned char inline_[
sizeof(T) * N];
465 Storage() noexcept {}