44#include < cassert>
55#include < cstddef>
66#include < memory>
7+ #include < type_traits>
78#include < utility>
89
910#include " openvic-simulation/core/Assert.hpp"
1011#include " openvic-simulation/core/template/Concepts.hpp"
1112#include " openvic-simulation/core/Typedefs.hpp"
1213
13- namespace OpenVic ::_detail {
14+ namespace OpenVic {
1415 // fixed capacity + not movable + not copyable
1516 template <typename T, typename Allocator = std::allocator<T>>
1617 class FixedVector {
@@ -27,6 +28,7 @@ namespace OpenVic::_detail {
2728 using reference = T&;
2829 using size_type = size_t ;
2930 using value_type = T;
31+ using allocator_type = Allocator;
3032
3133 constexpr size_t size () const { return _size; }
3234 constexpr size_t capacity () const { return _max_size; }
@@ -39,15 +41,21 @@ namespace OpenVic::_detail {
3941 * @brief Creates an uninitialised vector with fixed capacity
4042 */
4143 explicit FixedVector (const size_t capacity)
44+ : FixedVector(capacity, Allocator()) {}
45+
46+ FixedVector (const size_t capacity, std::type_identity_t <Allocator> const & alloc)
4247 : _max_size(capacity),
4348 _size (0 ),
44- _allocator(),
49+ _allocator(alloc ),
4550 _data_start_ptr(allocator_traits::allocate(_allocator, capacity)) {}
4651
4752 FixedVector (const size_t size, T const & value_for_all_indices)
53+ : FixedVector(size, value_for_all_indices, Allocator()) {}
54+
55+ FixedVector (const size_t size, T const & value_for_all_indices, std::type_identity_t <Allocator> const & alloc)
4856 : _max_size(size),
4957 _size(size),
50- _allocator(),
58+ _allocator(alloc ),
5159 _data_start_ptr(allocator_traits::allocate(_allocator, size)) {
5260 std::fill (_data_start_ptr, _data_start_ptr + size, value_for_all_indices);
5361 }
@@ -59,9 +67,19 @@ namespace OpenVic::_detail {
5967 // The type must be constructible from the generator's single return value
6068 && std::constructible_from<T, decltype(std::declval<GeneratorTemplateType>()(std::declval<size_t >()))>
6169 FixedVector(const size_t size, GeneratorTemplateType&& generator)
70+ : FixedVector(size, std::forward<GeneratorTemplateType>(generator), Allocator()) {
71+ }
72+
73+ // Generator (size_t i) -> U (where T is constructable from U)
74+ template <typename GeneratorTemplateType>
75+ // The generator must NOT return a tuple
76+ requires (!specialization_of<std::remove_cvref_t <std::invoke_result_t <GeneratorTemplateType, size_t >>, std::tuple>)
77+ // The type must be constructible from the generator's single return value
78+ && std::constructible_from<T, decltype(std::declval<GeneratorTemplateType>()(std::declval<size_t >()))>
79+ FixedVector(const size_t size, GeneratorTemplateType&& generator, std::type_identity_t <Allocator> const & alloc)
6280 : _max_size(size),
6381 _size(size),
64- _allocator(),
82+ _allocator(alloc ),
6583 _data_start_ptr(allocator_traits::allocate(_allocator, size)) {
6684 for (size_t i = 0 ; i < size; ++i) {
6785 allocator_traits::construct (
@@ -88,9 +106,28 @@ namespace OpenVic::_detail {
88106 };
89107 }
90108 FixedVector (const size_t size, GeneratorTemplateType&& generator)
109+ : FixedVector(size, std::forward<GeneratorTemplateType>(generator), Allocator()) {
110+ }
111+
112+ // Generator (size_t i) -> std::tuple<Args...> (where T is constructable from Args)
113+ template <typename GeneratorTemplateType>
114+ // The generator must return a tuple
115+ requires specialization_of<std::remove_cvref_t <std::invoke_result_t <GeneratorTemplateType, size_t >>, std::tuple>
116+ // The tuple must be constructible into a T
117+ && requires (GeneratorTemplateType&& generator) {
118+ {
119+ std::apply (
120+ [](auto &&... args) {
121+ T obj{std::forward<decltype (args)>(args)...};
122+ },
123+ generator (std::declval<size_t >())
124+ )
125+ };
126+ }
127+ FixedVector (const size_t size, GeneratorTemplateType&& generator, std::type_identity_t <Allocator> const & alloc)
91128 : _max_size(size),
92129 _size (size),
93- _allocator(),
130+ _allocator(alloc ),
94131 _data_start_ptr(allocator_traits::allocate(_allocator, size)) {
95132 for (size_t i = 0 ; i < size; ++i) {
96133 std::apply (
@@ -115,7 +152,7 @@ namespace OpenVic::_detail {
115152 clear ();
116153 allocator_traits::deallocate (_allocator, _data_start_ptr, _max_size);
117154 }
118-
155+
119156 using iterator = T*;
120157 using const_iterator = const T*;
121158
@@ -126,7 +163,7 @@ namespace OpenVic::_detail {
126163 iterator end () { return begin () + _size; }
127164 const_iterator end () const { return begin () + _size; }
128165 const_iterator cend () const { return cbegin () + _size; }
129-
166+
130167 using reverse_iterator = std::reverse_iterator<iterator>;
131168 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
132169
@@ -198,14 +235,9 @@ namespace OpenVic::_detail {
198235 }
199236 _size = 0 ;
200237 }
201- };
202- }
203238
204- #include < foonathan/memory/std_allocator.hpp>
205-
206- #include " openvic-simulation/utility/MemoryTracker.hpp"
207-
208- namespace OpenVic ::memory {
209- template <typename T, class RawAllocator = foonathan::memory::default_allocator>
210- using FixedVector = _detail::FixedVector<T, foonathan::memory::std_allocator<T, tracker<RawAllocator>>>;
239+ allocator_type get_allocator () const {
240+ return _allocator;
241+ }
242+ };
211243}
0 commit comments