どうやら P0843R13 inplace_vector が C++26 入りするみたいなので、紹介します。
概要
std::inplace_vector
はその容量がコンパイル時に決定される、メモリ上で要素が連続するコンテナ型です。
std::vector
などよりは std::array
に近く、要素はオブジェクトそのものに格納されます。
template <class T, size_t N>
class inplace_vector;
基本的には sizeof(size_t) + sizeof(T) * N
程度のサイズになるようですが、特殊な場合として N == 0
の時にはクラス全体のサイズが 0
になるよう定められています。
メンバ
std::inplace_vector
は std::vector
の持つメンバ関数を全て利用できますが、それに加えていくつかのメンバ関数が存在するようです。
try_emplace_back, try_push_back
template <class... Args>
constexpr pointer try_emplace_back(Args&&... args);
constexpr pointer try_push_back(const T& x);
constexpr pointer try_push_back(T&& x);
これらの関数は既存の emplace_back
や push_back
に対して、要素を追加できない時に例外を投げずに nullptr
を返します。
#include <cassert>
#include <inplace_vector>
int main() {
std::inplace_vector<int, 5> vec{3, 1, 4, 1};
assert(*vec.try_push_back(5) == 5);
assert(vec.try_push_back(9) == nullptr);
}
try_append_range
template <container-compatible-range<T> R>
constexpr ranges::borrowed_iterator_t<R> try_append_range(R&& rng);
C++23 で追加された append_range
の try_
版です。
append_range
も push_back
などと同様に void
を返しますが、 try_append_range
は追加できた要素の範囲 [first, last) の last を返します。
#include <algorithm>
#include <array>
#include <cassert>
#include <inplace_vector>
#include <ranges>
int main() {
std::inplace_vector<int, 5> vec{3, 1};
auto rng = std::views::iota(0, 5);
auto it = vec.try_append_range(rng);
assert(std::ranges::equal(vec, std::array{3, 1, 0, 1, 2}));
assert(it == rng.begin() + 3);
}
unchecked_emplace_back, unchecked_push_back
template <class... Args>
constexpr reference unchecked_emplace_back(Args&&...);
constexpr reference unchecked_push_back(const T& x);
constexpr reference unchecked_push_back(T&& x);
上記の try_
版に対し無条件に参照を返す版です。
unchecked_emplace_back(args...)
は *try_emplace_back(args...)
と、 unchecked_push_back(arg)
は *try_push_back(arg)
と等価です
既存実装
std::inplace_vector
のようなコンテナ型は、これまでにも static_vector
のような名前で使われてきました。 Boost.Container にも boost::container::static_vector
が実装されています。
参照
P0843R13 inplace_vector
https://eel.is/c++draft
https://github.com/cplusplus/papers/issues/114