Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma once
- #include <algorithm>
- #include <numeric>
- #include <cassert>
- #include <stdexcept>
- namespace API
- {
- template<typename T>
- class Container
- {
- public:
- using pointer = T*;
- using const_pointer = const T*;
- using iterator = T*; //aliases for generic code
- using const_iterator = const T*;
- using value_type = T;
- using size_type = size_t;
- using reference = T&;
- using const_reference = const T&;
- friend void swap(Container& a, Container& b) noexcept;
- Container() = default;
- explicit Container(size_type count) : _data(new T[count]), _count(count), _capacity(count){
- std::fill(begin(), end(), T());
- };
- explicit Container(const Container& that) : _data(new T[that._capacity]), _count(that._count), _capacity(that._capacity) {
- std::copy(begin(), end(), _data);
- }
- Container(Container&& that) noexcept {
- _count = that._count;
- _capacity = that._capacity;
- _data = that._data;
- that._data = nullptr;
- that._count = 0;
- that._capacity = 0;
- }
- Container& operator=(Container&& that) noexcept {
- swap(that);
- return *this;
- }
- void swap(Container& that) noexcept {
- using std::swap;
- swap(_data, that._data);
- swap(_count, that._count);
- swap(_capacity, that._capacity);
- }
- Container& operator=(const Container& that) { // copy assignment
- delete[] _data;
- _data = new T[that._capacity]; //overwrites an existing pointer
- _count = that._count;
- _capacity = that._capacity;
- std::copy(that.begin(), that.end(), _data);
- return *this;
- }
- ~Container() {
- //TODO: maybe have to call destructors or T (~T)
- delete[] _data;
- }
- void reserve(size_type newCapacity) {
- if (newCapacity <= _capacity) { return; } //never decrease the allocation
- pointer newBuffer = new T[newCapacity];
- std::move(begin(), end(), newBuffer);
- delete[] _data; //TODO: potentially need to deconstruct objects
- _data = newBuffer;
- _capacity = newCapacity;
- }
- void push_back(const T& value) {
- if (_capacity == 0) {
- reserve(2);
- }
- else if (_count == _capacity) {
- reserve(2 * _capacity);
- }
- _data[_count] = value;
- _count++;
- }
- reference at(size_type index) {
- if (index >= size()) {
- throw std::out_of_range("Container at() index is out of range!");
- }
- return _data[index];
- }
- const_reference at(size_type index) const {
- if (index >= size()) {
- throw std::out_of_range("Container at() index is out of range!");
- }
- return _data[index];
- }
- reference operator[](size_type index) noexcept{
- assert(index < size() && "Container operator[] index is out of range!");
- return _data[index];
- }
- const_reference operator[](size_type index) const noexcept {
- assert(index < size() && "Container operator[] index is out of range!");
- return _data[index];
- }
- reference front() noexcept {
- assert(!empty() && "front() on empty container is UB");
- return _data[0];
- }
- const_reference front() const noexcept {
- assert(!empty() && "front() on empty container is UB");
- return _data[0];
- }
- const_reference back() const noexcept {
- assert(!empty() && "back() on empty container is UB");
- return _data[size() - 1];
- }
- reference back() noexcept {
- assert(!empty() && "back() on empty container is UB");
- return _data[size() - 1];
- }
- [[nodiscard]] constexpr bool empty() const noexcept {
- return size() == 0;
- }
- size_type size() const noexcept {
- return _count;
- }
- //TODO: make free functions of these
- const_iterator begin() const noexcept { return _data; }
- const_iterator cbegin() const noexcept { return _data; }
- iterator begin() noexcept { return _data; }
- const_iterator end() const noexcept { return _data + _count; }
- const_iterator cend() const noexcept { return _data + _count; }
- iterator end() noexcept { return _data + _count; }
- private:
- T* _data = nullptr;
- size_type _count = 0;
- size_type _capacity = 0;
- };
- template<typename T>
- void swap(Container<T>& a, Container<T>& b) noexcept {
- a.swap(b);
- /*std::swap(a._capacity, b._capacity);
- std::swap(a._count, b._count);
- std::swap(a._data, b._data);*/
- }
- template<typename T>
- bool operator==(const Container<T>& lhs, const Container<T>& rhs) noexcept {
- if (std::size(lhs) != std::size(rhs)) { return false; }
- return std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs));
- }
- template<typename T>
- bool operator<(const Container<T>& lhs, const Container<T>& rhs) noexcept {
- return std::lexicographical_compare(lhs.begin(), lhs.end(),
- rhs.begin(), rhs.end());
- }
- template<typename T>
- bool operator!=(const Container<T>& lhs, const Container<T>& rhs) noexcept {
- return not(lhs == rhs);
- }
- template<typename T>
- bool operator>(const Container<T>& lhs, const Container<T>& rhs) noexcept {
- return rhs < lhs;
- }
- template<typename T>
- bool operator<=(const Container<T>& lhs, const Container<T>& rhs) noexcept {
- !(lhs > rhs);
- }
- template<typename T>
- bool operator>=(const Container<T>& lhs, const Container<T>& rhs) noexcept {
- !(lhs < rhs);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement