#pragma once #include #include #include #include #include namespace ft { template < class T, class Allocator = std::allocator > class vector; template void swap(vector& lhs, vector& rhs); template bool operator==(const vector& lhs, const vector& rhs); template bool operator!=(const vector& lhs, const vector& rhs); template bool operator<(const vector& lhs, const vector& rhs); template bool operator<=(const vector& lhs, const vector& rhs); template bool operator>(const vector& lhs, const vector& rhs); template bool operator>=(const vector& lhs, const vector& rhs); } template class ft::vector { public: typedef T value_type; typedef Allocator allocator_type; typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; typedef value_type& reference; typedef const value_type& const_reference; typedef typename Allocator::pointer pointer; class iterator { public: typedef iterator self_type; typedef reference reference_type; typedef T* pointer_type; private: pointer_type _ptr; public: iterator(pointer_type ptr) : _ptr(ptr) { } iterator(const self_type& src) : _ptr(src._ptr) { } reference_type operator*() { return *_ptr; } pointer_type operator->() { return _ptr; } self_type& operator++() { _ptr++; return *this; } self_type& operator++(int) { self_type tmp (*this); _ptr++; return tmp; } self_type operator--() { _ptr--; return *this; } self_type operator--(int) { self_type tmp (*this); _ptr--; return tmp; } self_type& operator+=(difference_type n) { *this = *this + n; return *this; } self_type operator+(difference_type n) { self_type tmp (*this); tmp += n; return tmp; } self_type operator-(difference_type n) { self_type tmp (*this); tmp -= n; return tmp; } self_type& operator-=(difference_type n) { *this = *this - n; return *this; } bool operator==(const self_type& other) const { return _ptr == other._ptr; } bool operator!=(const self_type& other) const { return !(*this == other); } }; class const_iterator { private: typedef iterator self_type; typedef const_reference reference_type; typedef const T* pointer_type; pointer_type _ptr; public: const_iterator(pointer_type ptr) : _ptr(ptr) { } const_iterator(const self_type& src) : _ptr(src._ptr) { } reference_type operator*() { return *_ptr; } pointer_type operator->() { return _ptr; } self_type& operator++() { _ptr++; return *this; } self_type& operator++(int) { self_type tmp (*this); _ptr++; return tmp; } self_type operator--() { _ptr--; return *this; } self_type operator--(int) { self_type tmp (*this); _ptr--; return tmp; } self_type& operator+=(difference_type n) { *this = *this + n; return *this; } self_type operator+(difference_type n) { self_type tmp (*this); tmp += n; return tmp; } self_type operator-(difference_type n) { self_type tmp (*this); tmp -= n; return tmp; } self_type& operator-=(difference_type n) { *this = *this - n; return *this; } bool operator==(const self_type& other) const { return _ptr == other._ptr; } bool operator!=(const self_type& other) const { return !(*this == other); } }; class reverse_iterator { private: typedef reverse_iterator self_type; typedef reference reference_type; typedef T* pointer_type; pointer_type _ptr; public: reverse_iterator(pointer_type ptr) : _ptr(ptr) { } reverse_iterator(const self_type& src) : _ptr(src._ptr) { } reference_type operator*() { return *_ptr; } pointer_type operator->() { return _ptr; } self_type& operator++() { _ptr--; return *this; } self_type& operator++(int) { self_type tmp (*this); _ptr--; return tmp; } self_type operator--() { _ptr++; return *this; } self_type operator--(int) { self_type tmp (*this); _ptr++; return tmp; } self_type& operator+=(difference_type n) { *this = *this - n; return *this; } self_type operator+(difference_type n) { self_type tmp (*this); tmp += n; return tmp; } self_type operator-(difference_type n) { self_type tmp (*this); tmp -= n; return tmp; } self_type& operator-=(difference_type n) { *this = *this + n; return *this; } bool operator==(const self_type& other) const { return _ptr == other._ptr; } bool operator!=(const self_type& other) const { return !(*this == other); } }; class const_reverse_iterator { private: typedef const_reverse_iterator self_type; typedef const_reference reference_type; typedef const T* pointer_type; pointer_type _ptr; public: const_reverse_iterator(pointer_type ptr) : _ptr(ptr) { } const_reverse_iterator(const self_type& src) : _ptr(src._ptr) { } reference_type operator*() { return *_ptr; } pointer_type operator->() { return _ptr; } self_type& operator++() { _ptr--; return *this; } self_type& operator++(int) { self_type tmp (*this); _ptr--; return tmp; } self_type operator--() { _ptr++; return *this; } self_type operator--(int) { self_type tmp (*this); _ptr++; return tmp; } self_type& operator+=(difference_type n) { *this = *this - n; return *this; } self_type operator+(difference_type n) { self_type tmp (*this); tmp += n; return tmp; } self_type operator-(difference_type n) { self_type tmp (*this); tmp -= n; return tmp; } self_type& operator-=(difference_type n) { *this = *this + n; return *this; } bool operator==(const self_type& other) const { return _ptr == other._ptr; } bool operator!=(const self_type& other) const { return !(*this == other); } }; private: size_type _size; size_type _capacity; T *_data; allocator_type _alloc; public: /* constructor */ vector() { vector(size_type(0), T(), allocator_type()); } explicit vector(const Allocator& alloc) { vector(size_type(0), T(), alloc); } explicit vector(size_type count, const T& value = T(), const Allocator& alloc = Allocator()) { _alloc = alloc; _size = count; _capacity = count; if (_capacity > 0) _data = _alloc.allocate(_capacity); for (size_type i = 0; i < count; i++) _alloc.construct(_data + i, value); } template vector(InputIt first, InputIt last, const Allocator& alloc = Allocator()) { _alloc = alloc; _size = 0; while (first + _size != last) _size += 1; _capacity = _size; if (_capacity > 0) _data = _alloc.allocate(_capacity); for (size_type i = 0; i < _size; i++) _alloc.construct(_data + i, *(first + i)); } vector(const vector& other) : _data(NULL) { *this = other; } /* destructor */ ~vector() { if (_data != NULL) { for (size_type i = 0; i < _size; i++) _alloc.destroy(_data + i); _alloc.deallocate(_data, _capacity); _size = 0; _capacity = 0; _data = NULL; } } /* operator= */ vector& operator=(const vector& other) { if (_data != NULL) { for (size_type i = 0; i < _size; i++) _alloc.destroy(_data + i); _alloc.deallocate(_data, _capacity); _size = 0; _capacity = 0; _data = NULL; } _alloc = allocator_type(); _size = other.size(); _capacity = other.size(); if (_capacity > 0) _data = _alloc.allocate(_capacity); for (size_type i = 0; i < other.size(); i++) _alloc.construct(_data + i, other._data[i]); return *this; } /* assign */ void assign(size_type count, const T& value) { *this = vector(count, value, _alloc); } template void assign(InputIt first, InputIt last) { *this = vector(first, last, _alloc); /* TODO */ } /* get_allocator */ allocator_type get_allocator() const { return _alloc; } /* ELEMENT ACCESS */ /* at */ reference at(size_type pos) { if (pos >= _size) throw std::out_of_range("pos out of bounds"); return _data[pos]; } const_reference at(size_type pos) const { if (pos >= _size) throw std::out_of_range("pos out of bounds"); return _data[pos]; } /* operator[] */ reference operator[](size_type pos) { return _data[pos]; } const_reference operator[](size_type pos) const { return _data[pos]; } /* front */ reference front() { return _data[0]; } const_reference front() const { return _data[0]; } /* back */ reference back() { return _data[_size - 1]; } const_reference back() const { return _data[_size - 1]; } /* data */ T* data() { return _data; } const T* data() const { return _data; } /* ITERATORS */ typename iterator::self_type begin() { return iterator(_data); } typename const_iterator::self_type begin() const { return const_iterator(_data); } typename iterator::self_type end() { return iterator(_data + _size); } typename const_iterator::self_type end() const { return const_iterator(_data + _size); } typename reverse_iterator::self_type rbegin() { return reverse_iterator(_data + _size - 1); } typename const_reverse_iterator::self_type rbegin() const { return const_reverse_iterator(_data + _size - 1); } typename reverse_iterator::self_type rend() { return reverse_iterator(_data - 1); } typename const_reverse_iterator::self_type rend() const { return const_reverse_iterator(_data - 1); } /* CAPACITY */ bool empty() const { return _size == 0; } size_type size() const { return _size; } size_type max_size() const { return std::numeric_limits::max(); } void reserve(size_type new_cap) { if (new_cap <= _capacity) return; if (new_cap > max_size()) throw std::length_error("new_cap > max_size()"); T *const new_data (_alloc.allocate(new_cap)); for (size_type i = 0; i < _size; i++) { _alloc.construct(new_data + i, _data[i]); _alloc.destroy(_data + i); } _alloc.deallocate(_data, _capacity); _capacity = new_cap; _data = new_data; } size_type capacity() const { return _capacity; } /* MODIFIERS */ /* clear */ void clear() { for (size_type i = 0; i < _size; i++) _alloc.destroy(_data + i); _size = 0; } /* insert */ iterator insert(const_iterator pos, const T& value); iterator insert(const_iterator pos, size_type count, const T& value); template iterator insert(const_iterator pos, InputIt first, InputIt last); /* TODO */ /* erase */ iterator erase(iterator pos); iterator erase(iterator first, iterator last); /* push_back */ void push_back(const T& value) { if (_size == _capacity) reserve(_size * 2); _alloc.construct(_data + _size, value); _size += 1; } /* pop_back */ void pop_back() { _alloc.destroy(_data + _size - 1); _size -= 1; } /* resize */ void resize(size_type count) { return resize(count, T()); } void resize(size_type count, const value_type& value) { if (count < _size) { for (size_type i = count; i < _size; i++) _alloc.destroy(_data + i); _size = count; return; } reserve(count); for (size_type i = _size; i < count; i++) _alloc.construct(_data + i, value); _size = count; } /* swap */ void swap(vector& other) { const size_type tmp_size (_size); const size_type tmp_capacity (_capacity); const T *tmp_data (_data); const allocator_type tmp_alloc (_alloc); _size = other._size; _capacity = other._capacity; _data = other._data; _alloc = other._alloc; other._size = tmp_size; other._capacity = tmp_capacity; other._data = tmp_data; other._alloc = tmp_alloc; } }; template void ft::swap(vector& lhs, vector& rhs) { lhs.swap(rhs); } template bool ft::operator==(const vector& lhs, const vector& rhs) { if (lhs.size() != rhs.size()) return false; for (typename vector::size_type i = 0; i < lhs.size(); i++) if (lhs[i] != rhs[i]) return false; return true; } template bool ft::operator!=(const vector& lhs, const vector& rhs) { return !(lhs == rhs); } template bool ft::operator<(const vector& lhs, const vector& rhs) { const typename vector::size_type end (lhs.size() < rhs.size() ? lhs.size() : rhs.size()); for (typename vector::size_type i = 0; i < end; i++) { if (lhs[i] < rhs[i]) return true; } return lhs.size() < rhs.size(); } template bool ft::operator<=(const vector& lhs, const vector& rhs) { return !(lhs > rhs); } template bool ft::operator>(const vector& lhs, const vector& rhs) { const typename vector::size_type end (lhs.size() < rhs.size() ? lhs.size() : rhs.size()); for (typename vector::size_type i = 0; i < end; i++) { if (lhs[i] > rhs[i]) return true; } return lhs.size() > rhs.size(); } template bool ft::operator>=(const vector& lhs, const vector& rhs) { return !(lhs < rhs); }