51 static_assert(N > 0,
"SmallVector requires at least 1 inline element. Use std::vector for N=0.");
52 static_assert(N < 65536,
"SmallVector inline capacity is too large. Use std::vector instead.");
56 using size_type = size_t;
57 using difference_type = std::ptrdiff_t;
59 using const_reference =
const T&;
61 using const_pointer =
const T*;
63 using const_iterator =
const T*;
95 ensureCapacity(init.size());
96 for (
const auto& v : init) {
103 ensureCapacity(other.rawSize());
104 for (
const auto& v : other) {
111 if (other.isInline()) {
114 const size_type n = other.size_;
115 for (size_type i = 0; i < n; ++i) {
116 new (inlineData() + i) T(std::move(other.inlineData()[i]));
117 other.inlineData()[i].~T();
120 storage_.heap_.ptr = other.storage_.heap_.ptr;
121 storage_.heap_.capacity = other.storage_.heap_.capacity;
134 if (
this != &other) {
137 ensureCapacity(other.rawSize());
138 for (
const auto& v : other) {
147 if (
this != &other) {
150 if (other.isInline()) {
154 const size_type n = other.size_;
155 for (size_type i = 0; i < n; ++i) {
156 new (inlineData() + i) T(std::move(other.inlineData()[i]));
157 other.inlineData()[i].~T();
160 storage_.heap_.ptr = other.storage_.heap_.ptr;
161 storage_.heap_.capacity = other.storage_.heap_.capacity;
176 reference operator[](size_type pos) {
180 const_reference operator[](size_type pos)
const {
193 return data()[rawSize() - 1];
197 return data()[rawSize() - 1];
202 return isInline() ? inlineData() : storage_.heap_.ptr;
205 const_pointer
data() const noexcept {
206 return isInline() ? inlineData() : storage_.heap_.ptr;
216 const_iterator
begin() const noexcept {
225 return data() + rawSize();
228 const_iterator
end() const noexcept {
229 return data() + rawSize();
232 const_iterator
cend() const noexcept {
233 return data() + rawSize();
240 return rawSize() == 0;
243 size_type
size() const noexcept {
252 return isInline() ? N : storage_.heap_.capacity;
261 ensureCapacity(newCap);
290 template <
typename... Args>
294 size_type sz = rawSize();
299 ptr = storage_.heap_.ptr;
302 size_type sz = rawSize();
303 if (sz == storage_.heap_.capacity) {
304 growToHeap(storage_.heap_.capacity * 2);
306 ptr = storage_.heap_.ptr;
308 size_type idx = rawSize();
309 new (ptr + idx) T(std::forward<Args>(args)...);
312 assert(rawSize() > 0 &&
"Size overflow into heap bit");
319 size_type sz = rawSize();
331 size_type sz = rawSize();
333 ensureCapacity(count);
335 for (size_type i = sz; i < count; ++i) {
339 }
else if (count < sz) {
341 for (size_type i = count; i < sz; ++i) {
355 void resize(size_type count,
const T& value) {
356 size_type sz = rawSize();
358 ensureCapacity(count);
360 for (size_type i = sz; i < count; ++i) {
361 new (ptr + i) T(value);
364 }
else if (count < sz) {
366 for (size_type i = count; i < sz; ++i) {
381 iterator
erase(const_iterator pos) {
383 size_type sz = rawSize();
384 size_type index = pos - ptr;
386 for (size_type i = index; i + 1 < sz; ++i) {
387 ptr[i] = std::move(ptr[i + 1]);
391 return data() + index;
399 static constexpr size_type kHeapBit = size_type(1) << (
sizeof(size_type) * 8 - 1);
400 static constexpr size_type kSizeMask = ~kHeapBit;
402 bool isInline() const noexcept {
403 return (size_ & kHeapBit) == 0;
406 size_type rawSize() const noexcept {
407 return size_ & kSizeMask;
411 void setSize(size_type s)
noexcept {
412 assert((s & kHeapBit) == 0 &&
"Size overflow into heap bit");
413 size_ = (size_ & kHeapBit) | s;
416 T* inlineData() noexcept {
417 return reinterpret_cast<T*
>(&storage_.inline_);
419 const T* inlineData() const noexcept {
420 return reinterpret_cast<const T*
>(&storage_.inline_);
423 void destroyAll() noexcept {
425 size_type sz = rawSize();
426 for (size_type i = 0; i < sz; ++i) {
438 DISPENSO_DISABLE_WARNING_PUSH
439 DISPENSO_DISABLE_WARNING_FREE_NONHEAP_OBJECT
440 ::operator
delete(storage_.heap_.ptr);
441 DISPENSO_DISABLE_WARNING_POP
447 void growToHeap(size_type newCap) {
448 T* newData =
static_cast<T*
>(::operator
new(newCap *
sizeof(T)));
450 size_type sz = rawSize();
452 for (size_type i = 0; i < sz; ++i) {
453 new (newData + i) T(std::move(oldData[i]));
458 ::operator
delete(storage_.heap_.ptr);
461 storage_.heap_.ptr = newData;
462 storage_.heap_.capacity = newCap;
463 size_ = kHeapBit | sz;
466 void ensureCapacity(size_type newCap) {
467 if (newCap <= N && isInline()) {
472 }
else if (newCap > storage_.heap_.capacity) {
485 alignas(T)
unsigned char inline_[
sizeof(T) * N];
487 Storage() noexcept {}