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> 53 template<
class T, decltype(auto) Default_>
58 value_type* allocate(std::size_t n) {
return static_cast<value_type*
>(::operator
new(n *
sizeof(value_type))); }
60 void deallocate(value_type* p, std::size_t) noexcept { ::operator
delete(p); }
63 void construct(U* p) noexcept(std::is_nothrow_default_constructible<U>::value) {
64 ::new (static_cast<void*>(p)) U(Default_);
67 template<
typename U,
typename... Args>
68 void construct(U* p, Args&&... args) {
69 ::new (p) U(std::forward<Args>(args)...);
78 template<
class T, decltype(auto) D1,
class U, decltype(auto) D2>
83 template<
class T, decltype(auto) D1,
class U, decltype(auto) D2>
88 template<
typename T,
typename Allocator>
93 std::weak_ptr<V*> _control;
94 typename V::size_type _index = 0;
97 using difference_type =
typename V::V::iterator::difference_type;
98 using value_type =
typename V::V::iterator::value_type;
99 using pointer =
typename V::V::iterator::pointer;
100 using reference =
typename V::V::iterator::reference;
101 using const_reference =
typename V::V::const_reference;
102 using iterator_category =
typename V::V::iterator::iterator_category;
105 Iterator(
typename V::size_type&& index,
const typename V::C& control)
106 : _control(control), _index(std::move(index)) {}
108 reference operator*();
109 const_reference operator*()
const;
123 if ( a._control.lock() != b._control.lock() )
124 throw InvalidArgument(
"cannot compare iterators into different vectors");
125 return a._index == b._index;
128 friend bool operator!=(
const Iterator& a,
const Iterator& b) {
return ! (a == b); }
131 if ( a._control.lock() != b._control.lock() )
132 throw InvalidArgument(
"cannot compare iterators into different vectors");
133 return a._index < b._index;
137 if ( a._control.lock() != b._control.lock() )
138 throw InvalidArgument(
"cannot compare iterators into different vectors");
139 return a._index <= b._index;
143 if ( a._control.lock() != b._control.lock() )
144 throw InvalidArgument(
"cannot compare iterators into different vectors");
145 return a._index > b._index;
149 if ( a._control.lock() != b._control.lock() )
150 throw InvalidArgument(
"cannot compare iterators into different vectors");
151 return a._index >= b._index;
155 if ( a._control.lock() != b._control.lock() )
156 throw InvalidArgument(
"cannot perform arithmetic with iterators into different vectors");
157 return a._index - b._index;
163 std::optional<std::reference_wrapper<V>> _container()
const;
166 template<
typename T,
typename Allocator>
170 std::weak_ptr<Vector<T, Allocator>*> _control;
171 typename V::size_type _index = 0;
174 using difference_type =
typename V::V::const_iterator::difference_type;
175 using value_type =
typename V::V::const_iterator::value_type;
176 using pointer =
typename V::V::const_iterator::pointer;
177 using reference =
typename V::V::const_iterator::reference;
178 using const_reference =
typename V::V::iterator::reference;
179 using iterator_category =
typename V::V::const_iterator::iterator_category;
182 ConstIterator(
typename V::size_type&& index,
const typename V::C& control)
183 : _control(control), _index(std::move(index)) {}
185 const_reference operator*()
const;
199 if ( a._control.lock() != b._control.lock() )
200 throw InvalidArgument(
"cannot compare iterators into different vectors");
201 return a._index == b._index;
207 if ( a._control.lock() != b._control.lock() )
208 throw InvalidArgument(
"cannot compare iterators into different vectors");
209 return a._index < b._index;
213 if ( a._control.lock() != b._control.lock() )
214 throw InvalidArgument(
"cannot compare iterators into different vectors");
215 return a._index <= b._index;
219 if ( a._control.lock() != b._control.lock() )
220 throw InvalidArgument(
"cannot compare iterators into different vectors");
221 return a._index > b._index;
225 if ( a._control.lock() != b._control.lock() )
226 throw InvalidArgument(
"cannot compare iterators into different vectors");
227 return a._index >= b._index;
231 if ( a._control.lock() != b._control.lock() )
232 throw InvalidArgument(
"cannot perform arithmetic with iterators into different vectors");
233 return a._index - b._index;
239 std::optional<std::reference_wrapper<V>> _container()
const;
255 template<
typename T,
typename Allocator>
256 class Vector :
protected std::vector<T, Allocator> {
259 static_assert(! std::is_same_v<T, bool>,
"'Vector' cannot be used with naked booleans, use 'Bool'");
261 using V = std::vector<T, Allocator>;
263 using size_type = integer::safe<uint64_t>;
264 using reference = T&;
265 using const_reference =
const T&;
269 using C = std::shared_ptr<Vector*>;
270 C _control = std::make_shared<Vector<T, Allocator>*>(
this);
276 Vector(
Vector&& other) noexcept : V(std::move(other)) {}
278 Vector(std::initializer_list<T>
init,
const Allocator& alloc = Allocator()) : V(std::move(init), alloc) {}
289 throw IndexError(
"vector is empty");
301 throw IndexError(
"vector is empty");
313 throw IndexError(
"vector is empty");
325 if ( i >= V::size() )
326 throw IndexError(
fmt(
"vector index %" PRIu64
" out of range", i));
339 if ( end <= start || start >= V::size() )
342 if ( end >= V::size() )
346 std::copy(V::begin() + start, V::begin() + end, std::back_inserter(v));
357 if ( end >= V::size() )
361 std::copy(V::begin(), V::begin() + end, std::back_inserter(v));
374 if ( &other ==
this )
377 static_cast<V&
>(*this) =
static_cast<const V&
>(other);
390 static_cast<V&
>(*this) =
static_cast<V&&
>(std::move(other));
401 if ( i >= V::size() )
402 throw IndexError(
fmt(
"vector index %" PRIu64
" out of range", i));
414 if ( i >= V::size() )
415 throw IndexError(
fmt(
"vector index %" PRIu64
" out of range", i));
427 if ( i >= V::size() )
428 throw IndexError(
fmt(
"vector index %" PRIu64
" out of range", i));
441 void assign(uint64_t i, T x) {
442 if ( i >= V::size() )
445 V::data()[i] = std::move(x);
465 V::insert(V::end(), other.V::begin(), other.V::end());
476 const auto index = pos._index;
477 if ( index > size() )
478 throw InvalidIterator(
fmt(
"index %s out of bounds", index));
480 V::insert(V::begin() + index.Ref(), value);
484 auto begin() {
return iterator(0U, _control); }
485 auto end() {
return iterator(size(), _control); }
493 size_type size()
const {
return V::size(); }
496 using typename V::value_type;
499 using V::emplace_back;
506 friend bool operator==(
const Vector& a,
const Vector& b) {
507 return static_cast<const V&
>(a) == static_cast<const V&>(b);
514 auto begin()
const& {
return this; }
515 auto end()
const& {
return this; }
516 auto empty()
const {
return true; }
517 auto size()
const {
return integer::safe<uint64_t>(0); }
520 template<
typename T,
typename Allocator>
524 template<
typename T,
typename Allocator>
528 template<
typename T,
typename Allocator>
532 template<
typename T,
typename Allocator>
537 template<
typename Allocator,
typename I,
typename O,
typename C>
540 for (
auto&& i : input )
541 output.emplace_back(func(i));
546 template<
typename Allocator,
typename I,
typename O,
typename C>
547 Vector<O, Allocator> make(
const C& input, std::function<O(I)> func, std::function<
bool(I)> pred) {
549 for (
auto&& i : input )
551 output.emplace_back(func(i));
558 namespace detail::adl {
559 template<
typename T,
typename Allocator>
561 using detail::adl::to_string;
567 template<
typename T,
typename Allocator>
569 return "<vector iterator>";
572 template<
typename T,
typename Allocator>
574 return "<const vector iterator>";
578 template<
typename T,
typename Allocator>
579 inline std::ostream& operator<<(std::ostream& out, const Vector<T, Allocator>& x) {
584 inline std::ostream& operator<<(std::ostream& out,
const vector::Empty& x) {
589 template<
typename T,
typename Allocator>
594 template<
typename T,
typename Allocator>
596 if (
auto&& c = _container() ) {
597 auto&& data = c->get();
599 if ( _index >= data.size() ) {
600 throw InvalidIterator(
fmt(
"index %s out of bounds", _index));
606 throw InvalidIterator(
"bound object has expired");
609 template<
typename T,
typename Allocator>
611 if (
auto&& c = _container() ) {
612 auto&& data = c->get();
614 if ( _index >= data.size() ) {
615 throw InvalidIterator(
fmt(
"index %s out of bounds", _index));
621 throw InvalidIterator(
"bound object has expired");
626 template<
typename T,
typename Allocator>
627 inline std::ostream& operator<<(std::ostream& out, const vector::Iterator<T, Allocator>& ) {
628 return out <<
"<vector iterator>";
631 template<
typename T,
typename Allocator>
632 inline std::ostream& operator<<(std::ostream& out, const vector::ConstIterator<T, Allocator>& ) {
633 return out <<
"<const vector iterator>";
638 template<
typename T,
typename Allocator>
640 if (
auto l = _control.lock() ) {
641 return {std::ref(**l)};
647 template<
typename T,
typename Allocator>
649 if (
auto&& c = _container() ) {
650 auto&& data = c->get();
652 if ( _index >= data.size() ) {
653 throw InvalidIterator(
fmt(
"index %s out of bounds", _index));
659 throw InvalidIterator(
"bound object has expired");
662 template<
typename T,
typename Allocator>
664 if (
auto l = _control.lock() ) {
665 return {std::ref(**l)};
Vector< T > sub(uint64_t start, uint64_t end) const
Definition: vector.h:338
std::string to_string(T &&x)
Definition: extension-points.h:26
void init()
Definition: init.cc:22
auto transform(const C &x, F f)
Definition: util.h:362
Vector< T > sub(uint64_t end) const
Definition: vector.h:356
const_iterator iteratorAt(uint64_t i) const
Definition: vector.h:324
Vector & operator=(const Vector &other)
Definition: vector.h:373
void pop_back()
Definition: vector.h:311
T operator[](uint64_t i) &&
Definition: vector.h:413
Vector operator+(const Vector &other) const
Definition: vector.h:453
const T & back() const
Definition: vector.h:299
const T & front() const
Definition: vector.h:287
const T & operator[](uint64_t i) const &
Definition: vector.h:400
Vector & operator+=(const Vector &other)
Definition: vector.h:464
Vector & operator=(Vector &&other) noexcept
Definition: vector.h:389
std::string join(const T &l, const std::string &delim="")
Definition: util.h:312
iterator insert(iterator pos, const T &value)
Definition: vector.h:475
T & operator[](uint64_t i) &
Definition: vector.h:426
std::string fmt(const char *fmt, const Args &... args)
Definition: fmt.h:13