@@ -117,4 +117,163 @@ struct id_traits<Id<Tag, Rep>> {
117117template <class T >
118118concept IdType = is_id_v<T>;
119119
120+ template <IdType IdT>
121+ class IdProvider {
122+ public:
123+ using id_type = std::remove_cv_t <IdT>;
124+ using rep = typename id_traits<id_type>::rep;
125+
126+ constexpr IdProvider (rep initialValue) : nextId(initialValue) {}
127+
128+ constexpr id_type getNewId () {
129+ if (unusedIds.empty ()) {
130+ return id_type (nextId++);
131+ } else {
132+ rep id = *unusedIds.begin ();
133+ unusedIds.erase (unusedIds.begin ());
134+ return id_type (id);
135+ }
136+ }
137+ constexpr id_type getNewId (id_type preferredId) {
138+ if (unusedIds.size () * 2 < nextId && unusedIds.contains (preferredId.get ())) {
139+ unusedIds.erase (preferredId.get ());
140+ return preferredId;
141+ }
142+ if (preferredId.get () == nextId || unusedIds.empty ()) {
143+ return id_type (nextId++);
144+ } else {
145+ rep id = *unusedIds.begin ();
146+ unusedIds.erase (unusedIds.begin ());
147+ return id_type (id);
148+ }
149+ }
150+ constexpr void releaseId (id_type id) {
151+ if (!isIdUsed (id)) {
152+ return ;
153+ }
154+ unusedIds.insert (id.get ());
155+ }
156+ constexpr bool isIdUsed (id_type id) const {
157+ return id.get () < nextId && !unusedIds.contains (id.get ());
158+ }
159+ constexpr id_type peekNext () const {
160+ return id_type (nextId);
161+ }
162+ void reset () {
163+ nextId = 0 ;
164+ unusedIds.clear ();
165+ }
166+ std::vector<id_type> getUsedIds () const {
167+ std::vector<id_type> usedIds;
168+ for (rep id = 0 ; id < nextId; ++id) {
169+ if (!unusedIds.contains (id)) {
170+ usedIds.push_back (id_type (id));
171+ }
172+ }
173+ return usedIds;
174+ }
175+ private:
176+ rep nextId;
177+ std::set<rep> unusedIds;
178+ };
179+
180+ template <IdType IdT>
181+ class LinearIdProvider {
182+ public:
183+ using id_type = std::remove_cv_t <IdT>;
184+ using rep = typename id_traits<id_type>::rep;
185+
186+ constexpr LinearIdProvider (rep initialValue) : nextId(initialValue) {}
187+
188+ constexpr id_type getNewId () {
189+ return id_type (nextId++);
190+ }
191+ constexpr id_type peekNext () const {
192+ return id_type (nextId);
193+ }
194+ constexpr id_type lastIdProvided () const {
195+ return idType (nextId - 1 );
196+ }
197+ void reset () {
198+ nextId = 0 ;
199+ }
200+
201+ private:
202+ rep nextId;
203+ };
204+
205+ template <IdType IdT, class T >
206+ class IdVector {
207+ public:
208+ using id_type = std::remove_cv_t <IdT>;
209+ using tag = typename id_traits<id_type>::tag;
210+ using rep = typename id_traits<id_type>::rep;
211+ using value_type = T;
212+
213+ static_assert (std::is_integral_v<rep>, " Id::rep must be an integral type" );
214+
215+ constexpr IdVector () = default;
216+ explicit IdVector (id_type n) : storage_(rep(n)) {}
217+ IdVector (id_type n, const T& value) : storage_(rep(n), value) {}
218+
219+ inline id_type size () const noexcept { return id_type{rep (storage_.size ())}; }
220+ inline bool empty () const noexcept { return storage_.empty (); }
221+
222+ inline id_type capacity () const noexcept { return id_type{rep (storage_.capacity ())}; }
223+
224+ inline void reserve (id_type n) { storage_.reserve (n.get ()); }
225+ inline void resize (id_type n) { storage_.resize (n.get ()); }
226+ inline void resize (id_type n, const T& value) { storage_.resize (n.get (), value); }
227+ inline void resizeWithOffset (id_type n, int offset) { storage_.resize (n.get () + offset); }
228+ inline void resizeWithOffset (id_type n, int offset, const T& value) { storage_.resize (n.get () + offset, value); }
229+
230+ inline void clear () noexcept { storage_.clear (); }
231+
232+ inline T& operator [](id_type id) { return storage_[id.get ()]; }
233+ inline const T& operator [](id_type id) const { return storage_[id.get ()]; }
234+
235+ inline T& at (id_type id) { return storage_.at (id.get ()); }
236+ inline const T& at (id_type id) const { return storage_.at (id.get ()); }
237+
238+ inline id_type push_back (const T& v) {
239+ storage_.push_back (v);
240+ return last_id_ ();
241+ }
242+ inline id_type push_back (T&& v) {
243+ storage_.push_back (std::move (v));
244+ return last_id_ ();
245+ }
246+ template <class ... Args>
247+ inline id_type emplace_back (Args&&... args) {
248+ storage_.emplace_back (std::forward<Args>(args)...);
249+ return last_id_ ();
250+ }
251+
252+ inline id_type begin_id () const noexcept { return id_type (0 ); }
253+ inline id_type end_id () const noexcept { return size (); }
254+
255+ inline bool contains (id_type id) const noexcept {
256+ return id.get () < storage_.size ();
257+ }
258+
259+ inline IdRange<tag, rep> ids () const {
260+ return range (begin_id (), end_id ());
261+ }
262+
263+ inline auto begin () noexcept { return storage_.begin (); }
264+ inline auto end () noexcept { return storage_.end (); }
265+ inline auto begin () const noexcept { return storage_.begin (); }
266+ inline auto end () const noexcept { return storage_.end (); }
267+ inline const std::vector<T>& raw () const noexcept { return storage_; }
268+ inline std::vector<T>& raw () noexcept { return storage_; }
269+
270+ private:
271+ inline id_type last_id_ () const {
272+ auto n = storage_.size ();
273+ return id_type{rep (n - 1 )};
274+ }
275+
276+ std::vector<T> storage_;
277+ };
278+
120279#endif /* id_h */
0 commit comments