ulfben

Container 2020 day 2

Nov 20th, 2020
465
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #pragma once
  2. #include <algorithm>
  3. #include <numeric>
  4. #include <cassert>
  5. #include <stdexcept>
  6. namespace API
  7. {
  8.     template<typename T>
  9.     class Container
  10.     {
  11.     public:
  12.         using pointer = T*;
  13.         using const_pointer = const T*;
  14.         using iterator = T*; //aliases for generic code
  15.         using const_iterator = const T*;
  16.         using value_type = T;
  17.         using size_type = size_t;
  18.         using reference = T&;
  19.         using const_reference = const T&;
  20.  
  21.         friend void swap(Container& a, Container& b) noexcept;
  22.  
  23.         Container() = default;
  24.         explicit Container(size_type count) : _data(new T[count]), _count(count), _capacity(count){
  25.             std::fill(begin(), end(), T());
  26.         };
  27.  
  28.         explicit Container(const Container& that) : _data(new T[that._capacity]), _count(that._count), _capacity(that._capacity)  {
  29.             std::copy(begin(), end(), _data);
  30.         }
  31.  
  32.         Container(Container&& that) noexcept {
  33.             _count = that._count;
  34.             _capacity = that._capacity;
  35.             _data = that._data;
  36.             that._data = nullptr;
  37.             that._count = 0;
  38.             that._capacity = 0;
  39.         }
  40.  
  41.         Container& operator=(Container&& that) noexcept {
  42.             swap(that);
  43.             return *this;
  44.         }
  45.        
  46.         void swap(Container& that) noexcept {
  47.             using std::swap;
  48.             swap(_data, that._data);
  49.             swap(_count, that._count);
  50.             swap(_capacity, that._capacity);
  51.         }
  52.  
  53.         Container& operator=(const Container& that) { // copy assignment
  54.             delete[] _data;
  55.             _data = new T[that._capacity]; //overwrites an existing pointer
  56.             _count = that._count;
  57.             _capacity = that._capacity;
  58.             std::copy(that.begin(), that.end(), _data);
  59.             return *this;          
  60.         }
  61.        
  62.         ~Container() {
  63.             //TODO: maybe have to call destructors or T (~T)
  64.             delete[] _data;
  65.         }
  66.  
  67.         void reserve(size_type newCapacity) {
  68.             if (newCapacity <= _capacity) { return;  } //never decrease the allocation
  69.             pointer newBuffer = new T[newCapacity];
  70.             std::move(begin(), end(), newBuffer);
  71.             delete[] _data; //TODO: potentially need to deconstruct objects
  72.             _data = newBuffer;
  73.             _capacity = newCapacity;
  74.         }
  75.  
  76.         void push_back(const T& value) {
  77.             if (_capacity == 0) {
  78.                 reserve(2);
  79.             }
  80.             else if (_count == _capacity) {
  81.                 reserve(2 * _capacity);
  82.             }
  83.             _data[_count] = value;
  84.             _count++;
  85.         }
  86.  
  87.         reference at(size_type index) {
  88.             if (index >= size()) {
  89.                 throw std::out_of_range("Container at() index is out of range!");
  90.             }
  91.             return _data[index];
  92.         }
  93.         const_reference at(size_type index) const {
  94.             if (index >= size()) {
  95.                 throw std::out_of_range("Container at() index is out of range!");
  96.             }
  97.             return _data[index];
  98.         }
  99.  
  100.         reference operator[](size_type index) noexcept{
  101.             assert(index < size() && "Container operator[] index is out of range!");
  102.             return _data[index];
  103.         }
  104.         const_reference operator[](size_type index) const noexcept {
  105.             assert(index < size() && "Container operator[] index is out of range!");
  106.             return _data[index];
  107.         }
  108.  
  109.         reference front() noexcept {
  110.             assert(!empty() && "front() on empty container is UB");
  111.             return _data[0];
  112.         }
  113.         const_reference front() const noexcept {
  114.             assert(!empty() && "front() on empty container is UB");
  115.             return _data[0];
  116.         }
  117.  
  118.         const_reference back() const noexcept {
  119.             assert(!empty() && "back() on empty container is UB");
  120.             return _data[size() - 1];
  121.         }
  122.         reference back() noexcept {
  123.             assert(!empty() && "back() on empty container is UB");
  124.             return _data[size() - 1];
  125.         }
  126.        
  127.         [[nodiscard]] constexpr bool empty() const noexcept {
  128.             return size() == 0;
  129.         }
  130.  
  131.         size_type size() const noexcept {
  132.             return _count;
  133.         }
  134.  
  135.         //TODO: make free functions of these
  136.         const_iterator begin() const noexcept { return _data; }    
  137.         const_iterator cbegin() const noexcept { return _data; }
  138.         iterator begin() noexcept { return _data; }
  139.  
  140.         const_iterator end() const noexcept { return _data + _count; }
  141.         const_iterator cend() const noexcept { return _data + _count; }    
  142.         iterator end() noexcept { return _data + _count; }
  143.  
  144.     private:
  145.         T* _data = nullptr;
  146.         size_type _count = 0;
  147.         size_type _capacity = 0;
  148.     };
  149.  
  150.     template<typename T>
  151.     void swap(Container<T>& a, Container<T>& b) noexcept {
  152.         a.swap(b);
  153.         /*std::swap(a._capacity, b._capacity);
  154.         std::swap(a._count, b._count);
  155.         std::swap(a._data, b._data);*/
  156.     }
  157.  
  158.     template<typename T>
  159.     bool operator==(const Container<T>& lhs, const Container<T>& rhs) noexcept {
  160.         if (std::size(lhs) != std::size(rhs)) { return false; }
  161.         return std::equal(std::begin(lhs), std::end(lhs), std::begin(rhs));
  162.     }
  163.     template<typename T>
  164.     bool operator<(const Container<T>& lhs, const Container<T>& rhs) noexcept {
  165.         return std::lexicographical_compare(lhs.begin(), lhs.end(),
  166.             rhs.begin(), rhs.end());
  167.     }
  168.  
  169.     template<typename T>
  170.     bool operator!=(const Container<T>& lhs, const Container<T>& rhs) noexcept {
  171.         return not(lhs == rhs);
  172.     }
  173.     template<typename T>
  174.     bool operator>(const Container<T>& lhs, const Container<T>& rhs) noexcept {
  175.         return rhs < lhs;
  176.     }
  177.     template<typename T>
  178.     bool operator<=(const Container<T>& lhs, const Container<T>& rhs) noexcept {
  179.         !(lhs > rhs);
  180.     }
  181.     template<typename T>
  182.     bool operator>=(const Container<T>& lhs, const Container<T>& rhs) noexcept {
  183.         !(lhs < rhs);
  184.     }
  185. }
RAW Paste Data