История изменений
Исправление KennyMinigun, (текущая версия) :
Всё новое всегда втыкается в индекс 0, сдвиная всё «назад».
Хм, а что если std::vector<std::optional<T>> storage
? Конец вектора трактовать как начало (ну или заставить вектор расти влево). Тогда:
void move_front(size_type at) {
// образуем дыры при перемещении в начало
storage.emplace_back(std::move(storage[storage.size() - at - 1]));
}
// at - индекс с конца
T& operator [](size_type at) {
auto iter = storage.rbegin() + at;
while (iter > storage.rend() && !iter->has_value()) {
++iter;
}
assert(iter > storage.rend());
return *iter;
}
// можно дергать временами (после N вызовов move_front), чтоб уменьшить время operator[]
void shrink_to_fit() {
storage.erase(std::remove_if(storage.begin(), storage.end(), [](const auto &el) {
return !el.has_value();
}));
}
Исправление KennyMinigun, :
Всё новое всегда втыкается в индекс 0, сдвиная всё «назад».
Хм, а что если std::vector<std::optional<T>> storage
? Конец вектора трактовать как начало (ну или заставить вектор расти влево). Тогда:
void move_front(size_type at) {
// образуем дыры при перемещении в начало
storage.emplace_back(std::move(storage[storage.size() - at - 1]));
}
// at - индекс с конца
T& operator [](size_type at) {
auto iter = storage.rbegin() + at;
while (iter > storage.rend() && !iter->has_value()) {
++iter;
}
assert(iter > storage.rend());
return *iter;
}
// можно дергать временами, чтоб уменьшить время operator[]
void shrink_to_fit() {
storage.erase(std::remove_if(storage.begin(), storage.end(), [](const auto &el) {
return !el.has_value();
}));
}
Исправление KennyMinigun, :
Всё новое всегда втыкается в индекс 0, сдвиная всё «назад».
Хм, а что если std::vector<std::optional<T>> storage
? Конец вектора трактовать как начало (ну или заставить вектор расти влево). Тогда:
void move_front(size_type at) {
// образуем дыры при перемещении в начало
storage.emplace_back(std::move(storage[storage.size() - at - 1]));
}
// at - индекс с конца
T& operator [](size_type at) {
auto iter = storage.rbegin() + at;
while (iter > storage.rend() && !iter->has_value()) {
++iter;
}
assert(iter > storage.rend());
return *iter;
}
// можно дергать временами, чтоб уменьшить время operator[]
void shrink_to_fit() {
storage.erase(std::remove_if(storage.begin(), storage.end(), [](std::optional<T> &el) {
return !el.has_value();
}));
}
Исправление KennyMinigun, :
Всё новое всегда втыкается в индекс 0, сдвиная всё «назад».
Хм, а что если std::vector<std::optional<T>> storage
? Конец вектора трактовать как начало (ну или заставить вектор расти влево). Тогда:
void move_front(size_type at) {
// образуем дыры при перемещении в начало
storage.emplace_back(std::move(storage[at]));
}
// at - индекс с конца
T& operator [](size_type at) {
auto iter = storage.rbegin() + at;
while (iter > storage.rend() && !iter->has_value()) {
++iter;
}
assert(iter > storage.rend());
return *iter;
}
// можно дергать временами, чтоб уменьшить время operator[]
void shrink_to_fit() {
storage.erase(std::remove_if(storage.begin(), storage.end(), [](std::optional<T> &el) {
return !el.has_value();
}));
}
Исправление KennyMinigun, :
Всё новое всегда втыкается в индекс 0, сдвиная всё «назад».
Хм, а что если std::vector<std::optional<T>> storage
? Конец вектора трактовать как начало (ну или заставить вектор расти влево). Тогда:
void move_front(size_type at) {
// образуем дыры при перемещении в начало
storage.emplace_back(std::move(storage[at]));
}
// at - индекс с конца
T& operator [](size_type at) {
auto iter = storage.rbegin() + at;
while (iter > storage.rend() && !iter->has_value()) {
++iter;
}
assert(iter != storage.rend());
return *iter;
}
// можно дергать временами, чтоб уменьшить время operator[]
void shrink_to_fit() {
storage.erase(std::remove_if(storage.begin(), storage.end(), [](std::optional<T> &el) {
return !el.has_value();
}));
}
Исправление KennyMinigun, :
Всё новое всегда втыкается в индекс 0, сдвиная всё «назад».
Хм, а что если std::vector<std::optional<T>> storage
? Конец вектора трактовать как начало (ну или заставить вектор расти влево). Тогда:
void move_front(size_type at) {
// образуем дыры при перемещении в начало
storage.emplace_back(std::move(storage[at]));
}
// at - индекс с конца
T& operator [](size_type at) {
auto iter = storage.rbegin() + at;
while (!iter->has_value() && iter > storage.rend()) {
++iter;
}
assert(iter != storage.rend());
return *iter;
}
// можно дергать временами, чтоб уменьшить время operator[]
void shrink_to_fit() {
storage.erase(std::remove_if(storage.begin(), storage.end(), [](std::optional<T> &el) {
return !el.has_value();
}));
}
Исправление KennyMinigun, :
Всё новое всегда втыкается в индекс 0, сдвиная всё «назад».
Хм, а что если std::vector<std::optional<T>> storage
? Конец вектора трактовать как начало (ну или заставить вектор расти влево). Тогда:
void move_front(size_type at) {
// образуем дыры при перемещении в начало
storage.emplace_back(std::move(storage[at]));
}
// at - индекс с конца
T& operator [](size_type at) {
auto iter = storage.rbegin() + at;
while (!iter->has_value() && iter > storage.rend()) {
++iter;
}
assert(iter != storage.rend());
return *iter;
}
// можно дергать временами, чтоб уменьшить время operator[]
void shrink_to_fit() {
storage.erase(std::remove_if(storage.begin(), storage.end(), [](std::optional<T> &el) {
return !el.has_value();
}));
}
Исходная версия KennyMinigun, :
Всё новое всегда втыкается в индекс 0, сдвиная всё «назад».
Хм, а что если std::vector<std::optional<T>> storage
? Конец вектора трактовать как начало (ну или заставить вектор расти влево). Тогда:
void move_front(size_type at) {
// образуем дыры при перемещении в начало
storage.emplace_back(std::move(storage[at]));
}
// at - индекс с конца
T& operator [](size_type at) {
while (!(storage.rbegin() + at)->has_value()) {
++at;
assert(at < storage.size());
}
return *storage[at];
}
// можно дергать временами, чтоб уменьшить время operator[]
void shrink_to_fit() {
storage.erase(std::remove_if(storage.begin(), storage.end(), [](std::optional<T> &el) {
return !el.has_value();
}));
}