Get the latest Blender, older versions, or experimental builds.
Stay up-to-date with the new features in the latest Blender releases.
Access production assets and knowledge from the open movies.
Documentation on the usage and features in Blender.
Latest development updates, by Blender developers.
Guidelines, release notes and development docs.
A platform to collect and share results of the Blender Benchmark.
The yearly event that brings the community together.
Support core development with a monthly contribution.
Perform a single donation with more payment options available.
Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.
/* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include <algorithm>
#include "BLI_vector.hh"
namespace blender {
/**
* A VectorList is a vector of vectors.
*
* VectorList can be used when:
* 1) Don't know up front the number of elements that will be added to the list. Use array or
* vector.reserve when known up front.
* 2) Number of reads/writes doesn't require sequential access
* of the whole list. A vector ensures memory is sequential which is fast when reading, writing can
* have overhead when the reserved memory is full.
* When a VectorList reserved memory is full it will allocate memory for the new items, breaking
* the sequential access. Within each allocated memory block the elements are ordered sequentially.
*/
template<typename T, int64_t CapacityStart = 32, int64_t CapacitySoftLimit = 4096>
class VectorList {
public:
using UsedVector = Vector<T, 0>;
private:
* Contains the individual vectors. There must always be at least one vector
Vector<UsedVector> vectors_;
VectorList()
{
this->append_vector();
}
void append(const T &value)
this->append_as(value);
void append(T &&value)
this->append_as(std::move(value));
template<typename ForwardT> void append_as(ForwardT &&value)
UsedVector &vector = this->ensure_space_for_one();
vector.append_unchecked_as(std::forward<ForwardT>(value));
UsedVector *begin()
return vectors_.begin();
UsedVector *end()
return vectors_.end();
const UsedVector *begin() const
const UsedVector *end() const
T &last()
return vectors_.last().last();
int64_t size() const
int64_t result = 0;
for (const UsedVector &vector : *this) {
result += vector.size();
return result;
UsedVector &ensure_space_for_one()
UsedVector &vector = vectors_.last();
if (LIKELY(!vector.is_at_capacity())) {
return vector;
return vectors_.last();
void append_vector()
const int64_t new_vector_capacity = this->get_next_vector_capacity();
vectors_.append({});
vectors_.last().reserve(new_vector_capacity);
int64_t get_next_vector_capacity()
if (vectors_.is_empty()) {
return CapacityStart;
return std::min(vectors_.last().capacity() * 2, CapacitySoftLimit);
};
} // namespace blender