Difference between revisions of "cpp/container/inplace vector"
m (-stray {{elink}}) |
m (→Member types: "Member type" => "Type". It would be convenient to have "id="-anchor in {{dsc inc}} and other similar templates.) |
||
(12 intermediate revisions by 2 users not shown) | |||
Line 8: | Line 8: | ||
}} | }} | ||
− | {{tt|inplace_vector}} is a dynamically-resizable array with contiguous inplace storage | + | {{tt|inplace_vector}} is a dynamically-resizable array with contiguous inplace storage. The elements of type {{tt|T}} are stored and properly aligned within the object itself. The capacity of internal storage is fixed at compile-time and is equal to {{tt|N}}. |
− | {{ | + | The elements are stored contiguously, which means that elements can be accessed not only through iterators or random-access {{c/core|operator[]}}, but also using offsets to regular pointers to elements. A pointer to an element of an {{tt|inplace_vector}} may be passed to any function that expects a pointer to an element of a C-array. |
− | + | ||
− | + | ||
− | {{ | + | |
− | + | ||
− | {{tt| | + | The {{tt|inplace_vector}} models {{named req|Container}}, {{named req|ReversibleContainer}}, {{named req|ContiguousContainer}}, and {{named req|SequenceContainer}}, including most of the [[cpp/named_req/SequenceContainer#Optional operations|optional sequence container requirements]], except that the {{tt|push_front}}, {{tt|emplace_front}}, {{tt|pop_front}}, and {{tt|prepend_range}} member functions are not provided. |
− | + | For any {{tt|N}}, {{c|std::inplace_vector<T, N>::iterator}} and {{c|std::inplace_vector<T, N>::const_iterator}} meet the {{named req|ConstexprIterator}} requirements. | |
− | + | If {{c|N > 0}} and {{c|std::is_trivial_v<T>}} is {{c|false}}, then member functions of {{tt|inplace_vector}} are not {{lsd|cpp/language/constant expression#Usable in constant expressions}}. | |
− | {{ | + | The specialization {{c|std::inplace_vector<T, 0>}} is a {{named req|TrivialType}} and is empty. |
− | + | Any member function of {{c|std::inplace_vector<T, N>}} that would cause insertion beyond the capacity {{tt|N}} throws {{lc|std::bad_alloc}}. | |
− | + | ||
− | + | The complexity of common operations on {{tt|inplace_vector}}s is as follows: | |
− | + | * Random access to an element via {{rlt|operator at|operator[]}} or {{rlt|at|at()}} – constant: {{math|𝓞(1)}}. | |
+ | * Insertion or removal of an element at the end – constant: {{math|𝓞(1)}}. | ||
+ | * Insertion or removal of elements at the end – linear in the number of elements inserted/removed: {{math|𝓞(n)}}. | ||
+ | * Insertion or removal of elements in the beginning or in the middle – linear in the number of elements inserted/removed plus the distance to the end of the vector: {{math|𝓞(n)}}. | ||
===Iterator invalidation=== | ===Iterator invalidation=== | ||
− | {{ | + | {{tt|std::inplace_vector}} iterator invalidation guarantees differ from {{lc|std::vector}}: |
− | + | * moving an {{tt|inplace_vector}} invalidates all iterators; | |
− | + | * swapping two {{tt|inplace_vector}}s invalidates all iterators (during swap, the iterator will continue to point to the same array element, and may thus change its value). | |
− | + | The following member functions potentially invalidate iterators: | |
+ | {{rlt|operator{{=}}}}, | ||
+ | {{rlt|assign}}, | ||
+ | {{rlt|assign_range}}, | ||
+ | {{rlt|clear}}, | ||
+ | {{rlt|emplace}}, | ||
+ | {{rlt|erase}}, | ||
+ | {{rlt|insert}}, | ||
+ | {{rlt|insert_range}}, | ||
+ | {{rlt|pop_back}}, | ||
+ | {{rlt|resize}}, and | ||
+ | {{rlt|swap}}. | ||
+ | |||
+ | The following member functions potentially invalidate {{rlt|end}} iterator only: | ||
+ | {{rlt|append_range}}, | ||
+ | {{rlt|emplace_back}}, | ||
+ | {{rlt|push_back}}, | ||
+ | {{rlt|try_append_range}}, | ||
+ | {{rlt|try_emplace_back}}, | ||
+ | {{rlt|try_push_back}}, | ||
+ | {{rlt|unchecked_emplace_back}}, and | ||
+ | {{rlt|unchecked_push_back}}. | ||
===Template parameters=== | ===Template parameters=== | ||
{{par begin}} | {{par begin}} | ||
− | {{par|T|element type. | + | {{par|T|element type. Must be {{named req|MoveConstructible}} and {{named req|MoveAssignable}}.}} |
{{par|N|capacity, i.e. the maximum number of elements in the {{tt|inplace_vector}} (might be {{c|0}}).}} | {{par|N|capacity, i.e. the maximum number of elements in the {{tt|inplace_vector}} (might be {{c|0}}).}} | ||
{{par end}} | {{par end}} | ||
− | |||
===Member types=== | ===Member types=== | ||
{{dsc begin}} | {{dsc begin}} | ||
− | {{dsc hitem| | + | {{dsc hitem|Type|Definition}} |
{{dsc inc|cpp/container/dsc value_type|inplace_vector}} | {{dsc inc|cpp/container/dsc value_type|inplace_vector}} | ||
{{dsc inc|cpp/container/dsc size_type|inplace_vector}} | {{dsc inc|cpp/container/dsc size_type|inplace_vector}} | ||
Line 102: | Line 120: | ||
{{dsc inc|cpp/container/dsc append_range|inplace_vector}} | {{dsc inc|cpp/container/dsc append_range|inplace_vector}} | ||
{{dsc inc|cpp/container/dsc try_append_range|inplace_vector}} | {{dsc inc|cpp/container/dsc try_append_range|inplace_vector}} | ||
− | |||
{{dsc inc|cpp/container/dsc clear|inplace_vector}} | {{dsc inc|cpp/container/dsc clear|inplace_vector}} | ||
{{dsc inc|cpp/container/dsc erase|inplace_vector}} | {{dsc inc|cpp/container/dsc erase|inplace_vector}} | ||
Line 116: | Line 133: | ||
===Notes=== | ===Notes=== | ||
− | + | The number of elements in a {{tt|inplace_vector}} may vary dynamically up to a fixed capacity because elements are stored within the object itself similarly to {{lc|std::array}}. However, objects are initialized as they are inserted into {{tt|inplace_vector}} unlike C arrays or {{lc|std::array}} , which must construct all elements on instantiation. | |
+ | |||
+ | {{tt|inplace_vector}} is useful in environments where dynamic memory allocations are undesired. | ||
− | |||
− | |||
− | |||
{{feature test macro|__cpp_lib_inplace_vector|std=C++26|value=202406L|{{tt|std::inplace_vector}}: dynamically-resizable vector with fixed capacity inplace storage}} | {{feature test macro|__cpp_lib_inplace_vector|std=C++26|value=202406L|{{tt|std::inplace_vector}}: dynamically-resizable vector with fixed capacity inplace storage}} | ||
===Example=== | ===Example=== | ||
− | |||
{{example | {{example | ||
|code= | |code= | ||
+ | #include <algorithm> | ||
+ | #include <array> | ||
+ | #include <cassert> | ||
#include <inplace_vector> | #include <inplace_vector> | ||
− | |||
int main() | int main() | ||
{ | { | ||
+ | std::inplace_vector<int, 4> v1{0, 1, 2}; | ||
+ | assert(v1.max_size() == 4); | ||
+ | assert(v1.capacity() == 4); | ||
+ | assert(v1.size() == 3); | ||
+ | assert(std::ranges::equal(v1, std::array{0, 1, 2})); | ||
+ | assert(v1[0] == 0); | ||
+ | assert(v1.at(0) == 0); | ||
+ | assert(v1.front() == 0); | ||
+ | assert(*v1.begin() == 0); | ||
+ | assert(v1.back() == 2); | ||
+ | v1.push_back(3); | ||
+ | assert(v1.back() == 3); | ||
+ | assert(std::ranges::equal(v1, std::array{0, 1, 2, 3})); | ||
+ | v1.resize(3); | ||
+ | assert(std::ranges::equal(v1, std::array{0, 1, 2})); | ||
+ | assert(v1.try_push_back(3) != nullptr); | ||
+ | assert(v1.back() == 3); | ||
+ | assert(v1.size() == 4); | ||
+ | assert(v1.try_push_back(13) == nullptr); // no place | ||
+ | assert(v1.back() == 3); | ||
+ | assert(v1.size() == 4); | ||
+ | v1.clear(); | ||
+ | assert(v1.size() == 0); | ||
+ | assert(v1.empty()); | ||
} | } | ||
− | + | }} | |
− | }} | + | |
===See also=== | ===See also=== | ||
Line 145: | Line 185: | ||
===External links=== | ===External links=== | ||
{{elink begin}} | {{elink begin}} | ||
− | {{elink|[https://www.boost.org/doc/libs/release/doc/html | + | {{elink|[https://godbolt.org/z/5P78aG5xE {{tt|inplace_vector}}] — A reference implementation of {{stddoc|P0843R14}} ({{tt|std::inplace_vector}}).}} |
− | {{elink|[https://github.com/questor/eastl/blob/master/fixed_vector.h#L71 | + | {{elink|[https://www.boost.org/doc/libs/release/doc/html/container/non_standard_containers.html#container.non_standard_containers.static_vector {{tt|static_vector}}] — Boost.Container implements inplace vector as a standalone type with its own guarantees.}} |
− | {{elink|[https://github.com/facebook/folly/blob/master/folly/docs/small_vector.md | + | {{elink|[https://github.com/questor/eastl/blob/master/fixed_vector.h#L71 {{tt|fixed_vector}}] — EASTL implements inplace vector via an extra template parameter.}} |
− | {{elink|[https:// | + | {{elink|[https://github.com/facebook/folly/blob/master/folly/docs/small_vector.md {{tt|small_vector}}] — Folly also implements inplace vector via an extra template parameter.}} |
+ | {{elink|[https://howardhinnant.github.io/stack_alloc.html {{tt|stack_alloc}}] — Howard Hinnant's Custom allocators that emulate {{tt|std::inplace_vector}} on top of {{lc|std::vector}}.}} | ||
{{elink end}} | {{elink end}} | ||
{{langlinks|de|es|fr|it|ja|pl|pt|ru|zh}} | {{langlinks|de|es|fr|it|ja|pl|pt|ru|zh}} |
Latest revision as of 14:26, 1 November 2024
Defined in header <inplace_vector>
|
||
template< class T, |
(since C++26) | |
inplace_vector
is a dynamically-resizable array with contiguous inplace storage. The elements of type T
are stored and properly aligned within the object itself. The capacity of internal storage is fixed at compile-time and is equal to N
.
The elements are stored contiguously, which means that elements can be accessed not only through iterators or random-access operator[], but also using offsets to regular pointers to elements. A pointer to an element of an inplace_vector
may be passed to any function that expects a pointer to an element of a C-array.
The inplace_vector
models Container, ReversibleContainer, ContiguousContainer, and SequenceContainer, including most of the optional sequence container requirements, except that the push_front
, emplace_front
, pop_front
, and prepend_range
member functions are not provided.
For any N
, std::inplace_vector<T, N>::iterator and std::inplace_vector<T, N>::const_iterator meet the ConstexprIterator requirements.
If N > 0 and std::is_trivial_v<T> is false, then member functions of inplace_vector
are not usable in constant expressions.
The specialization std::inplace_vector<T, 0> is a TrivialType and is empty.
Any member function of std::inplace_vector<T, N> that would cause insertion beyond the capacity N
throws std::bad_alloc.
The complexity of common operations on inplace_vector
s is as follows:
- Random access to an element via
operator[]
orat()
– constant: 𝓞(1). - Insertion or removal of an element at the end – constant: 𝓞(1).
- Insertion or removal of elements at the end – linear in the number of elements inserted/removed: 𝓞(n).
- Insertion or removal of elements in the beginning or in the middle – linear in the number of elements inserted/removed plus the distance to the end of the vector: 𝓞(n).
Contents |
[edit] Iterator invalidation
std::inplace_vector
iterator invalidation guarantees differ from std::vector:
- moving an
inplace_vector
invalidates all iterators; - swapping two
inplace_vector
s invalidates all iterators (during swap, the iterator will continue to point to the same array element, and may thus change its value).
The following member functions potentially invalidate iterators:
operator=
,
assign
,
assign_range
,
clear
,
emplace
,
erase
,
insert
,
insert_range
,
pop_back
,
resize
, and
swap
.
The following member functions potentially invalidate end
iterator only:
append_range
,
emplace_back
,
push_back
,
try_append_range
,
try_emplace_back
,
try_push_back
,
unchecked_emplace_back
, and
unchecked_push_back
.
[edit] Template parameters
T | - | element type. Must be MoveConstructible and MoveAssignable. |
N | - | capacity, i.e. the maximum number of elements in the inplace_vector (might be 0).
|
[edit] Member types
Type | Definition |
value_type
|
T
|
size_type
|
std::size_t |
difference_type
|
std::ptrdiff_t |
reference
|
value_type& |
const_reference
|
const value_type& |
pointer
|
value_type* |
const_pointer
|
const value_type* |
iterator
|
implementation-defined LegacyRandomAccessIterator and random_access_iterator to value_type
|
const_iterator
|
implementation-defined LegacyRandomAccessIterator and random_access_iterator to const value_type
|
reverse_iterator
|
std::reverse_iterator<iterator> |
const_reverse_iterator
|
std::reverse_iterator<const_iterator> |
[edit] Member functions
constructs the inplace_vector (public member function) | |
destructs the inplace_vector (public member function) | |
assigns values to the container (public member function) | |
assigns values to the container (public member function) | |
assigns a range of values to the container (public member function) | |
Element access | |
access specified element with bounds checking (public member function) | |
access specified element (public member function) | |
access the first element (public member function) | |
access the last element (public member function) | |
direct access to the underlying contiguous storage (public member function) | |
Iterators | |
returns an iterator to the beginning (public member function) | |
returns an iterator to the end (public member function) | |
returns a reverse iterator to the beginning (public member function) | |
returns a reverse iterator to the end (public member function) | |
Size and capacity | |
checks whether the container is empty (public member function) | |
returns the number of elements (public member function) | |
[static] |
returns the maximum possible number of elements (public static member function) |
[static] |
returns the number of elements that can be held in currently allocated storage (public static member function) |
changes the number of elements stored (public member function) | |
[static] |
reserves storage (public static member function) |
[static] |
reduces memory usage by freeing unused memory (public static member function) |
Modifiers | |
inserts elements (public member function) | |
inserts a range of elements (public member function) | |
constructs element in-place (public member function) | |
constructs an element in-place at the end (public member function) | |
tries to construct an element in-place at the end (public member function) | |
unconditionally constructs an element in-place at the end (public member function) | |
adds an element to the end (public member function) | |
tries to add an element to the end (public member function) | |
unconditionally adds an element to the end (public member function) | |
removes the last element (public member function) | |
adds a range of elements to the end (public member function) | |
tries to add a range of elements to the end (public member function) | |
clears the contents (public member function) | |
erases elements (public member function) | |
swaps the contents (public member function) |
[edit] Non-member functions
specializes the std::swap algorithm (function template) | |
erases all elements satisfying specific criteria (function template) | |
(C++26) |
lexicographically compares the values of two inplace_vector s (function template) |
[edit] Notes
The number of elements in a inplace_vector
may vary dynamically up to a fixed capacity because elements are stored within the object itself similarly to std::array. However, objects are initialized as they are inserted into inplace_vector
unlike C arrays or std::array , which must construct all elements on instantiation.
inplace_vector
is useful in environments where dynamic memory allocations are undesired.
Feature-test macro | Value | Std | Feature |
---|---|---|---|
__cpp_lib_inplace_vector |
202406L | (C++26) | std::inplace_vector : dynamically-resizable vector with fixed capacity inplace storage
|
[edit] Example
#include <algorithm> #include <array> #include <cassert> #include <inplace_vector> int main() { std::inplace_vector<int, 4> v1{0, 1, 2}; assert(v1.max_size() == 4); assert(v1.capacity() == 4); assert(v1.size() == 3); assert(std::ranges::equal(v1, std::array{0, 1, 2})); assert(v1[0] == 0); assert(v1.at(0) == 0); assert(v1.front() == 0); assert(*v1.begin() == 0); assert(v1.back() == 2); v1.push_back(3); assert(v1.back() == 3); assert(std::ranges::equal(v1, std::array{0, 1, 2, 3})); v1.resize(3); assert(std::ranges::equal(v1, std::array{0, 1, 2})); assert(v1.try_push_back(3) != nullptr); assert(v1.back() == 3); assert(v1.size() == 4); assert(v1.try_push_back(13) == nullptr); // no place assert(v1.back() == 3); assert(v1.size() == 4); v1.clear(); assert(v1.size() == 0); assert(v1.empty()); }
[edit] See also
dynamic contiguous array (class template) | |
(C++11) |
fixed-sized inplace contiguous array (class template) |
double-ended queue (class template) |
[edit] External links
inplace_vector — A reference implementation of P0843R14 (std::inplace_vector ).
| |
static_vector — Boost.Container implements inplace vector as a standalone type with its own guarantees.
| |
fixed_vector — EASTL implements inplace vector via an extra template parameter.
| |
small_vector — Folly also implements inplace vector via an extra template parameter.
| |
stack_alloc — Howard Hinnant's Custom allocators that emulate std::inplace_vector on top of std::vector.
|