20 #include <initializer_list> 27 #include <type_traits> 31 #include <hilti/rt/extension-points.h> 32 #include <hilti/rt/fmt.h> 33 #include <hilti/rt/iterator.h> 34 #include <hilti/rt/safe-int.h> 35 #include <hilti/rt/types/vector_fwd.h> 36 #include <hilti/rt/util.h> 48 template<
class T, T Default_>
53 value_type* allocate(std::size_t n) {
return static_cast<value_type*
>(::operator
new(n *
sizeof(value_type))); }
55 void deallocate(value_type* p, std::size_t) noexcept { ::operator
delete(p); }
58 void construct(U* p) noexcept(std::is_nothrow_default_constructible<U>::value) {
59 ::new (static_cast<void*>(p)) U(Default_);
62 template<
typename U,
typename... Args>
63 void construct(U* p, Args&&... args) {
64 ::new (p) U(std::forward<Args>(args)...);
73 template<
class T, T D1,
class U, U D2>
78 template<
class T, T D1,
class U, U D2>
83 template<
typename T,
typename Allocator>
88 std::weak_ptr<V*> _control;
89 typename V::size_type _index = 0;
92 using difference_type =
typename V::V::iterator::difference_type;
93 using value_type =
typename V::V::iterator::value_type;
94 using pointer =
typename V::V::iterator::pointer;
95 using reference =
typename V::V::iterator::reference;
96 using const_reference =
typename V::V::const_reference;
97 using iterator_category =
typename V::V::iterator::iterator_category;
100 Iterator(
typename V::size_type&& index,
const typename V::C& control)
101 : _control(control), _index(std::move(index)) {}
103 reference operator*();
104 const_reference operator*()
const;
118 if ( a._control.lock() != b._control.lock() )
119 throw InvalidArgument(
"cannot compare iterators into different vectors");
120 return a._index == b._index;
123 friend bool operator!=(
const Iterator& a,
const Iterator& b) {
return ! (a == b); }
126 if ( a._control.lock() != b._control.lock() )
127 throw InvalidArgument(
"cannot compare iterators into different vectors");
128 return a._index < b._index;
132 if ( a._control.lock() != b._control.lock() )
133 throw InvalidArgument(
"cannot compare iterators into different vectors");
134 return a._index <= b._index;
138 if ( a._control.lock() != b._control.lock() )
139 throw InvalidArgument(
"cannot compare iterators into different vectors");
140 return a._index > b._index;
144 if ( a._control.lock() != b._control.lock() )
145 throw InvalidArgument(
"cannot compare iterators into different vectors");
146 return a._index >= b._index;
150 if ( a._control.lock() != b._control.lock() )
151 throw InvalidArgument(
"cannot perform arithmetic with iterators into different vectors");
152 return a._index - b._index;
158 std::optional<std::reference_wrapper<V>> _container()
const;
161 template<
typename T,
typename Allocator>
165 std::weak_ptr<Vector<T, Allocator>*> _control;
166 typename V::size_type _index = 0;
169 using difference_type =
typename V::V::const_iterator::difference_type;
170 using value_type =
typename V::V::const_iterator::value_type;
171 using pointer =
typename V::V::const_iterator::pointer;
172 using reference =
typename V::V::const_iterator::reference;
173 using const_reference =
typename V::V::iterator::reference;
174 using iterator_category =
typename V::V::const_iterator::iterator_category;
177 ConstIterator(
typename V::size_type&& index,
const typename V::C& control)
178 : _control(control), _index(std::move(index)) {}
180 const_reference operator*()
const;
194 if ( a._control.lock() != b._control.lock() )
195 throw InvalidArgument(
"cannot compare iterators into different vectors");
196 return a._index == b._index;
202 if ( a._control.lock() != b._control.lock() )
203 throw InvalidArgument(
"cannot compare iterators into different vectors");
204 return a._index < b._index;
208 if ( a._control.lock() != b._control.lock() )
209 throw InvalidArgument(
"cannot compare iterators into different vectors");
210 return a._index <= b._index;
214 if ( a._control.lock() != b._control.lock() )
215 throw InvalidArgument(
"cannot compare iterators into different vectors");
216 return a._index > b._index;
220 if ( a._control.lock() != b._control.lock() )
221 throw InvalidArgument(
"cannot compare iterators into different vectors");
222 return a._index >= b._index;
226 if ( a._control.lock() != b._control.lock() )
227 throw InvalidArgument(
"cannot perform arithmetic with iterators into different vectors");
228 return a._index - b._index;
234 std::optional<std::reference_wrapper<V>> _container()
const;
250 template<
typename T,
typename Allocator>
251 class Vector :
protected std::vector<T, Allocator> {
254 static_assert(! std::is_same_v<T, bool>,
"'Vector' cannot be used with naked booleans, use 'Bool'");
256 using V = std::vector<T, Allocator>;
258 using size_type = integer::safe<uint64_t>;
259 using reference = T&;
260 using const_reference =
const T&;
264 using C = std::shared_ptr<Vector*>;
265 C _control = std::make_shared<Vector<T, Allocator>*>(
this);
271 Vector(
Vector&& other) noexcept : V(std::move(other)) {}
273 Vector(std::initializer_list<T>
init,
const Allocator& alloc = Allocator()) : V(std::move(init), alloc) {}
284 throw IndexError(
"vector is empty");
296 throw IndexError(
"vector is empty");
308 throw IndexError(
"vector is empty");
320 if ( i >= V::size() )
321 throw IndexError(
fmt(
"vector index %" PRIu64
" out of range", i));
334 if ( end <= start || start >= V::size() )
337 if ( end >= V::size() )
341 std::copy(V::begin() + start, V::begin() + end, std::back_inserter(v));
352 if ( end >= V::size() )
356 std::copy(V::begin(), V::begin() + end, std::back_inserter(v));
369 static_cast<V&
>(*this) =
static_cast<const V&
>(other);
382 static_cast<V&
>(*this) =
static_cast<V&&
>(std::move(other));
393 if ( i >= V::size() )
394 throw IndexError(
fmt(
"vector index %" PRIu64
" out of range", i));
406 if ( i >= V::size() )
407 throw IndexError(
fmt(
"vector index %" PRIu64
" out of range", i));
419 if ( i >= V::size() )
420 throw IndexError(
fmt(
"vector index %" PRIu64
" out of range", i));
433 void assign(uint64_t i, T x) {
434 if ( i >= V::size() )
437 V::data()[i] = std::move(x);
457 V::insert(V::end(), other.V::begin(), other.V::end());
468 const auto index = pos._index;
469 if ( index > size() )
470 throw InvalidIterator(
fmt(
"index %s out of bounds", index));
472 V::insert(V::begin() + index.Ref(), value);
476 auto begin() {
return iterator(0u, _control); }
477 auto end() {
return iterator(size(), _control); }
485 size_type size()
const {
return V::size(); }
488 using typename V::value_type;
491 using V::emplace_back;
498 friend bool operator==(
const Vector& a,
const Vector& b) {
499 return static_cast<const V&
>(a) == static_cast<const V&>(b);
506 auto begin()
const& {
return this; }
507 auto end()
const& {
return this; }
508 auto empty()
const {
return true; }
509 auto size()
const {
return integer::safe<uint64_t>(0); }
512 template<
typename T,
typename Allocator>
516 template<
typename T,
typename Allocator>
520 template<
typename T,
typename Allocator>
524 template<
typename T,
typename Allocator>
529 template<
typename Allocator,
typename I,
typename O,
typename C>
532 for (
auto&& i : input )
533 output.emplace_back(func(i));
538 template<
typename Allocator,
typename I,
typename O,
typename C>
539 Vector<O, Allocator> make(
const C& input, std::function<O(I)> func, std::function<
bool(I)> pred) {
541 for (
auto&& i : input )
543 output.emplace_back(func(i));
550 namespace detail::adl {
551 template<
typename T,
typename Allocator>
553 using detail::adl::to_string;
559 template<
typename T,
typename Allocator>
561 return "<vector iterator>";
564 template<
typename T,
typename Allocator>
566 return "<const vector iterator>";
570 template<
typename T,
typename Allocator>
571 inline std::ostream& operator<<(std::ostream& out, const Vector<T, Allocator>& x) {
576 inline std::ostream& operator<<(std::ostream& out,
const vector::Empty& x) {
581 template<
typename T,
typename Allocator>
586 template<
typename T,
typename Allocator>
588 if (
auto&& c = _container() ) {
589 auto&& data = c->get();
591 if ( _index >= data.size() ) {
592 throw InvalidIterator(
fmt(
"index %s out of bounds", _index));
598 throw InvalidIterator(
"bound object has expired");
601 template<
typename T,
typename Allocator>
603 if (
auto&& c = _container() ) {
604 auto&& data = c->get();
606 if ( _index >= data.size() ) {
607 throw InvalidIterator(
fmt(
"index %s out of bounds", _index));
613 throw InvalidIterator(
"bound object has expired");
618 template<
typename T,
typename Allocator>
619 inline std::ostream& operator<<(std::ostream& out, const vector::Iterator<T, Allocator>& ) {
620 return out <<
"<vector iterator>";
623 template<
typename T,
typename Allocator>
624 inline std::ostream& operator<<(std::ostream& out, const vector::ConstIterator<T, Allocator>& ) {
625 return out <<
"<const vector iterator>";
630 template<
typename T,
typename Allocator>
632 if (
auto l = _control.lock() ) {
633 return {std::ref(**l)};
639 template<
typename T,
typename Allocator>
641 if (
auto&& c = _container() ) {
642 auto&& data = c->get();
644 if ( _index >= data.size() ) {
645 throw InvalidIterator(
fmt(
"index %s out of bounds", _index));
651 throw InvalidIterator(
"bound object has expired");
654 template<
typename T,
typename Allocator>
656 if (
auto l = _control.lock() ) {
657 return {std::ref(**l)};
Vector< T > sub(uint64_t start, uint64_t end) const
Definition: vector.h:333
std::string to_string(T &&x)
Definition: extension-points.h:26
void init()
Definition: init.cc:18
auto transform(const C &x, F f)
Definition: util.h:331
Vector< T > sub(uint64_t end) const
Definition: vector.h:351
const_iterator iteratorAt(uint64_t i) const
Definition: vector.h:319
Vector & operator=(const Vector &other)
Definition: vector.h:368
void pop_back()
Definition: vector.h:306
T operator[](uint64_t i) &&
Definition: vector.h:405
Vector operator+(const Vector &other) const
Definition: vector.h:445
const T & back() const
Definition: vector.h:294
const T & front() const
Definition: vector.h:282
const T & operator[](uint64_t i) const &
Definition: vector.h:392
Vector & operator+=(const Vector &other)
Definition: vector.h:456
Vector & operator=(Vector &&other) noexcept
Definition: vector.h:381
std::string join(const T &l, const std::string &delim="")
Definition: util.h:281
iterator insert(iterator pos, const T &value)
Definition: vector.h:467
T & operator[](uint64_t i) &
Definition: vector.h:418
std::string fmt(const char *fmt, const Args &... args)
Definition: fmt.h:13