TGViewer
Грокаем C++ Грокаем C++ @grokaemcpp · 9.36K subscribers
Post #1128 3.66K
​​std::inplace_vector
#опытным

Стандартная библиотека традиционно запаздывает с внедрением полезного функционала.

Вот у нас есть std::vector. Прекрасный контейнер, расширяемый. более менее все им пользуются. Однако у него есть проблема - динамические аллокации. От них не уйти. А если вам они не нужны, то вы вынуждены использовать другие инструменты. Да и еще и ограниченное использование вектора в constexpr контексте.

Ну ладно. Есть std::array. Нет скрытых аллокаций, давно можно использовать в constexpr. Красота.

Но как бы не так: не расширяемый он. Еще и элементы должны быть созданы сразу все и должны соответствовать требованию DefaultConstructable.

Короче опять недостатки.

Но в С++26 появился контейнер, который объединяет преимущества std::vector и std::array. Называется он std::inplace_vector.

По сути это динамически расширяемый массив с фиксированной в compile-time емкостью:

1️⃣ Элементы массива хранятся прям внутри объекта, поэтому нет никаких дополнительных аллокаций.

2️⃣ Объект inplace_vector сразу при создании содержит буфер размера capacity.

3️⃣ Можно создать объект без элементов вообще и изменять их набор как угодно во время выполнения программы. Главное не превышать capacity.

4️⃣ Так как этот массив не предполагает дополнительных динамических аллокаций, то контейнер можно полноценно использовать в constexpr контексте.

Рассмотрим небольшой примерчик, где нам нужно отфильтровать из std::array пложительные числа и возвести их в квадрат:

template<size_t N>
constexpr std::inplace_vector<int, N> square_positive(const std::array<int, N>& arr) {
std::inplace_vector<int, N> result;
for (int x : arr) {
if (x > 0 && result.size() < result.capacity()) {
result.push_back(x * x);
}
}
return result;
}

int main() {
constexpr std::array<int, 6> data = {-3, 5, -1, 7, 0, 4};
constexpr auto squares = square_positive<6, 6>(data);
static_assert(squares.size() == 3);
static_assert(squares.capacity() == 6);
static_assert(squares[0] == 25);
static_assert(squares[1] == 49);
static_assert(squares[2] == 16);
return 0;
}


Мы не можем заранее сказать, сколько элементов вернет функция square_positive. Но мы можем гарантировать, что их количество <= размеру входного массива.

Создается inplace_vector пустым и элементы накидываются в него по очереди.

Проверки static_assert гарантируют, что все вычисления происходят в compile-time.

Еще одна особенность - у inplace_vector меньше требований к типу своих элементов:

struct S {
S() = delete;
S(int) { }
};

std::array<S, 5> arr; // compile error: S does not have a default constructor

std::inplace_vector<S, 5> inplace_vec; // ok


Так как std::array создает сразу все свои элементы, конструирование arr завершится ошибкой, потому что S не имеет конструктора по умолчанию. Но inplace_vec успешно создается, потому что не имеет этого требования.

Также std::inplace_vector - хороший пример того, что стандартная библиотека в новых стандартах старается поддерживать апи с использованием исключений и без них. Есть принципиально 2 разных подхода к добавлению элементов в этот массив:

👉🏿 constexpr reference push_back( const T& value ) — классический вариант, который выбрасывает std::bad_alloc при попытке превысить capacity.

👉🏿 constexpr std::optional<reference> try_push_back( const T& value ) - добавляет элемент и возвращает на него ссылку или не добавляет элемент и возвращает std::nullopt. То есть ошибка обрабатывается с помощью возвращаемого значения

Есть кстати еще метод constexpr reference unchecked_push_back( const T& value );, который забивает на все проверки и перекладывает эту ответственность на пользователя. В случае превышения емкости получаем UB.

В общем, крутой новый контейнер, который явно найдет себе место в системах с ограничениями кучи или суперпроизводительном софте.

Combine advantages. Stay cool.

#cpp26 #STL
  • ❤ 20
  • 👍 12
  • 😁 6
  • 🔥 4
  • ❤‍🔥 3
More from @grokaemcpp
  1. Oct 8, 2026​​Strict weak ordering #опытным На первый взгляд, всё выглядит рабочим: мы создаём 40 зака…
  2. Oct 7, 2026​​Где-то баг... #опытным Вот вам код: struct Order { int price; int id; }; int main() { st…
  3. Oct 5, 2026Откуда spurious wakeup на кондваре? #опытным У кондваров есть метод std::condition_variabl…
  4. Oct 1, 2026​​Stacktrace. Tips #опытным Чтобы полноценно работать со стандартными трейсами, нужно знат…
  5. Sep 28, 2026​​Stacktrace #опытным Одна из проблема исключений - непонятно, откуда оно прилетело. Ну да…
  6. Sep 25, 2026​​std::spanstream #опытным Радостная весть для всех, кто пользуется iostreams! В C++23 доб…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →