Line data Source code
1 : #pragma once 2 : 3 : #include <cstring> 4 : #include <iostream> 5 : #include <vector> 6 : #include "exceptions.hpp" 7 : 8 : // ============ 9 : // Declarations 10 : // ============ 11 : 12 : template <typename T> 13 : class vectorf 14 : { 15 : public: 16 : // === Constructors === 17 : 18 : // Constructor to create an UNINITIALIZED vector 19 : // WARNING: Good for performance, but make sure to never use any uninitialized 20 : // elements! First argument: number of elements 21 : vectorf(const size_t &); 22 : 23 : // Constructor to create an initialized vectorf 24 : // Argument: a vector containing the elements of vectorf 25 : // Number of elements is inferred automatically 26 : vectorf(const std::vector<T> &); 27 : 28 : // Copy constructor to create a new vector with the same elements as an 29 : // existing vector 30 : vectorf(const vectorf &); 31 : 32 : // Move constructor to move the elements of an existing vector to a new vector 33 : vectorf(vectorf &&); 34 : 35 : // === Member functions === 36 : 37 : // Overloaded operator = to assign the elements of one vector to another 38 : // vector 39 : vectorf &operator=(const vectorf &); 40 : 41 : // Overloaded operator = to move the elements of one vector to another vector 42 : vectorf &operator=(vectorf &&); 43 : 44 : // Member function used to obtain (but not modify) the size or length of the 45 : // vector 46 : size_t get_size() const; 47 : 48 : // Overloaded operator () used to access vector elements WITHOUT range 49 : // checking The indices start from 1: v(2) would be the element at row 2 First 50 : // version: returns a reference, thus allows modification of the element 51 : T &operator()(const size_t &); 52 : 53 : // Overloaded operator () used to access vector elements WITHOUT range 54 : // checking The indices start from 1: v(2) would be the element at row 2 55 : // Second version: does not return a reference and declared as const, 56 : // does not allow modification of the element 57 : T operator()(const size_t &) const; 58 : 59 : // Static member function used to set the character width of the elements 60 : // when printing a vector (will be used with std::setw) 61 : static void set_output_width(const int &); 62 : 63 : // === Friend functions === 64 : 65 : // Overloaded binary operator << used to easily print out a matrix to a stream 66 : template <typename U> 67 : friend std::ostream &operator<<(std::ostream &, const vectorf<U> &); 68 : 69 : private: 70 : // The number of rows 71 : size_t size{0}; 72 : 73 : // A pointer to an array storing the elements of the vector 74 : T *elements{nullptr}; 75 : 76 : // A smart pointer to manage the memory allocated for the elements 77 : std::unique_ptr<T[]> smart{nullptr}; 78 : 79 : // The character width of the elements when printing a matrix (will be used 80 : // with std::setw) 81 : static int output_width; 82 : }; 83 : 84 : // Initialize output_width to have a default value of 5 85 : template <typename T> 86 : int vectorf<T>::output_width{5}; 87 : 88 : // ============== 89 : // Implementation 90 : // ============== 91 : 92 : // === Constructors === 93 : 94 : // Uninitialized constructor 95 : template <typename T> 96 225 : vectorf<T>::vectorf(const size_t &input_size) : size(input_size) 97 : { 98 223 : if (size == 0) throw sayMessage{"Size of vector must be positive.\n"}; 99 222 : smart.reset(new T[ size ]); 100 221 : elements = smart.get(); 101 221 : } 102 : 103 : template <typename T> 104 33 : vectorf<T>::vectorf(const std::vector<T> &v) 105 : { 106 33 : size = v.size(); 107 33 : smart.reset(new T[ size ]); 108 33 : elements = smart.get(); 109 33 : std::memcpy(elements, &v[ 0 ], size * sizeof(T)); 110 33 : } 111 : 112 : // Copy constructor 113 : template <typename T> 114 3 : vectorf<T>::vectorf(const vectorf<T> &v) : size(v.size) 115 : { 116 3 : smart.reset(new T[ size ]); 117 3 : elements = smart.get(); 118 3 : std::memcpy(elements, v.elements, size * sizeof(T)); 119 3 : } 120 : 121 : // Move constructor 122 : template <typename T> 123 1 : vectorf<T>::vectorf(vectorf<T> &&v) : size(v.size) 124 : { 125 1 : smart = move(v.smart); 126 1 : elements = smart.get(); 127 1 : v.size = 0; 128 1 : v.elements = nullptr; 129 1 : } 130 : 131 : // === Member functions === 132 : 133 : // Copy assignment 134 : template <typename T> 135 3 : vectorf<T> &vectorf<T>::operator=(const vectorf<T> &v) 136 : { 137 3 : if (v.size != size) 138 1 : throw sayMessage{"Copy assignment requires equal vector size.\n"}; 139 2 : if (elements == v.elements) return *this; 140 1 : size = v.size; 141 1 : smart.reset(new T[ size ]); 142 1 : elements = smart.get(); 143 1 : std::memcpy(elements, v.elements, size * sizeof(T)); 144 1 : return *this; 145 : } 146 : 147 : // Move assignment 148 : template <typename T> 149 3 : vectorf<T> &vectorf<T>::operator=(vectorf<T> &&v) 150 : { 151 3 : if (v.size != size) 152 1 : throw sayMessage{"Move assignment requires equal vector size.\n"}; 153 2 : if (elements == v.elements) return *this; 154 1 : size = v.size; 155 1 : smart = move(v.smart); 156 1 : elements = smart.get(); 157 1 : v.size = 0; 158 1 : v.elements = nullptr; 159 1 : return *this; 160 : } 161 : 162 : template <typename T> 163 132 : inline size_t vectorf<T>::get_size() const 164 : { 165 132 : return size; 166 : } 167 : 168 : // With reference 169 : template <typename T> 170 1451 : inline T &vectorf<T>::operator()(const size_t &row) 171 : { 172 1451 : return elements[ row - 1 ]; 173 : } 174 : 175 : // No reference 176 : template <typename T> 177 659 : inline T vectorf<T>::operator()(const size_t &row) const 178 : { 179 659 : return elements[ row - 1 ]; 180 : } 181 : 182 : // For pretty printing 183 : template <typename T> 184 : inline void vectorf<T>::set_output_width(const int &w) 185 : { 186 : output_width = w; 187 : } 188 : 189 : // === Friend functions === 190 : 191 : template <typename T> 192 : std::ostream &operator<<(std::ostream &out, const vectorf<T> &v) 193 : { 194 : if (v.size == 0) 195 : out << "()\n"; 196 : else 197 : { 198 : out << "( "; 199 : for (size_t i{1}; i <= v.size; i++) 200 : { 201 : out << std::setw(v.output_width) << v(i) << ' '; 202 : } 203 : out << ")\n"; 204 : } 205 : return out; 206 : }