Kenneth Bruen
3 years ago
commit
5789f53721
5 changed files with 251 additions and 0 deletions
@ -0,0 +1,22 @@
|
||||
CXX?=g++
|
||||
|
||||
.PHONY: debug run clean |
||||
|
||||
example: obj/example.o |
||||
${CXX} $^ -o $@
|
||||
|
||||
run: example |
||||
./example
|
||||
|
||||
debug: |
||||
COMPILE_FLAGS="-D DEBUG" make -B example
|
||||
|
||||
obj: |
||||
@if [ ! -d obj ]; then mkdir obj; fi
|
||||
|
||||
obj/%.o: %.cpp | obj |
||||
${CXX} ${COMPILE_FLAGS} -c $^ -o $@
|
||||
|
||||
clean: |
||||
@if [ -d obj ]; then echo rm -r obj; rm -r obj; fi
|
||||
@if [ -f example ]; then echo rm example; rm example; fi
|
@ -0,0 +1,29 @@
|
||||
# DynArray: basic dynamic array (list/vector) implementation |
||||
|
||||
Why? Why not. |
||||
|
||||
## How to run? |
||||
|
||||
### Got make? |
||||
|
||||
```shell |
||||
make run |
||||
``` |
||||
|
||||
### No make? |
||||
|
||||
```shell |
||||
g++ example.cpp -o example |
||||
./example |
||||
``` |
||||
|
||||
### Windows? |
||||
|
||||
```powershell |
||||
g++ example.cpp -o example.exe |
||||
.\example.exe |
||||
``` |
||||
|
||||
### Windows without `g++`? |
||||
|
||||
I never compiled something using `msvc` from the terminal. I guess make a new Visual Studio project, copy-paste the files in there and have fun, idk. |
@ -0,0 +1,160 @@
|
||||
#pragma once |
||||
|
||||
#ifdef DEBUG |
||||
#define TMP_DEBUG_12345 DEBUG |
||||
#undef DEBUG |
||||
#include <iostream> |
||||
using std::cerr; |
||||
#define DEBUG (cerr << "[DynArray " << this << "] ") |
||||
#endif |
||||
|
||||
template <class T> |
||||
class DynArray { |
||||
private: |
||||
T* _buffer; |
||||
size_t _length; |
||||
size_t _capacity; |
||||
|
||||
public: |
||||
explicit DynArray(size_t capacity = 64) |
||||
: _buffer(new T[capacity]) |
||||
, _length(0)
|
||||
, _capacity(capacity) { |
||||
#ifdef DEBUG |
||||
DEBUG << "New array with capacity " << capacity << '\n'; |
||||
#endif |
||||
} |
||||
|
||||
~DynArray() { |
||||
#ifdef DEBUG |
||||
DEBUG << "Destroyed" << '\n'; |
||||
#endif |
||||
delete[] _buffer; |
||||
} |
||||
|
||||
size_t size() const { |
||||
return _length; |
||||
} |
||||
|
||||
size_t length() const { |
||||
return _length; |
||||
} |
||||
|
||||
operator bool() const { |
||||
return length() > 0; |
||||
} |
||||
|
||||
size_t capacity() const { |
||||
return _capacity; |
||||
} |
||||
|
||||
void push_back(T element) { |
||||
if (_length + 1 > _capacity) { |
||||
#ifdef DEBUG |
||||
DEBUG << "Push attempt when length and capacity are " << _capacity << ", reallocating" << '\n'; |
||||
#endif |
||||
T *new_buffer = new T[_capacity * 2]; |
||||
for (size_t i = 0; i < _capacity; ++i) { |
||||
new_buffer[i] = _buffer[i]; |
||||
} |
||||
delete[] _buffer; |
||||
_buffer = new_buffer; |
||||
_capacity *= 2; |
||||
} |
||||
_buffer[_length++] = element; |
||||
} |
||||
|
||||
DynArray<T>& operator<<(T element) { |
||||
push_back(element); |
||||
return *this; |
||||
} |
||||
|
||||
void pop_back() { |
||||
_length--; |
||||
} |
||||
|
||||
T& operator[](size_t index) { |
||||
return _buffer[index]; |
||||
} |
||||
|
||||
const T& operator[](size_t index) const { |
||||
return _buffer[index]; |
||||
} |
||||
|
||||
// Iterator bullshit
|
||||
class iterator { |
||||
private: |
||||
DynArray<T>* _arr; |
||||
size_t _index; |
||||
public: |
||||
// Default constructible
|
||||
iterator() : _arr(nullptr), _index(-1) {} |
||||
iterator(DynArray<T> &arr, size_t index = 0) : _arr(&arr), _index(index) {} |
||||
// Copy constructible
|
||||
iterator(const iterator &it) : _arr(it._arr), _index(it._index) {} |
||||
|
||||
// Copy assignable
|
||||
iterator& operator=(const iterator& it) { |
||||
_arr = it._arr; |
||||
_index = it._index; |
||||
} |
||||
|
||||
// Comparable
|
||||
bool operator==(const iterator& it) const { |
||||
return _arr == it._arr && _index == it._index; |
||||
} |
||||
|
||||
bool operator!=(const iterator& it) const { |
||||
return !(*this == it); |
||||
} |
||||
|
||||
// Dereferencable
|
||||
T& operator*() { |
||||
return (*_arr)[_index]; |
||||
} |
||||
const T& operator*() const { |
||||
return (*_arr)[_index]; |
||||
} |
||||
|
||||
T* operator->() { |
||||
return &((*_arr)[_index]); |
||||
} |
||||
const T* operator->() const { |
||||
return &((*_arr)[_index]); |
||||
} |
||||
|
||||
// Can be incremented
|
||||
iterator& operator++() { |
||||
_index++; |
||||
return *this; |
||||
} |
||||
|
||||
iterator operator++(int) { |
||||
auto copy = *this; |
||||
++*this; |
||||
return copy; |
||||
} |
||||
}; |
||||
|
||||
iterator begin() { |
||||
return iterator(*this); |
||||
} |
||||
const iterator begin() const { |
||||
return iterator(*this); |
||||
} |
||||
|
||||
iterator end() { |
||||
return iterator(*this, size()); |
||||
} |
||||
const iterator end() const { |
||||
return iterator(*this, size()); |
||||
} |
||||
}; |
||||
|
||||
#ifdef TMP_DEBUG_12345 |
||||
#ifdef DEBUG |
||||
#undef DEBUG |
||||
#endif |
||||
#define DEBUG TMP_DEBUG_12345 |
||||
#undef TMP_DEBUG_12345 |
||||
#endif |
@ -0,0 +1,38 @@
|
||||
#include <iostream> |
||||
#include <random> |
||||
using std::cout; |
||||
using std::cin; |
||||
|
||||
#include "dynarray.hpp" |
||||
|
||||
int main() { |
||||
size_t n; |
||||
cout << "How many numbers to generate? "; |
||||
cin >> n; |
||||
|
||||
std::default_random_engine r_eng; |
||||
DynArray<std::default_random_engine::result_type> arr; |
||||
for (auto i = 0; i < n; i++) |
||||
{ |
||||
arr << r_eng(); |
||||
} |
||||
cout << '\n'; |
||||
|
||||
cout << "Size: " << arr.size() << '\n'; |
||||
cout << "Capacity: " << arr.capacity() << '\n'; |
||||
cout << "Elements: ["; |
||||
bool first = true; |
||||
for (auto elem : arr) |
||||
{ |
||||
if (!first) { |
||||
cout << ", "; |
||||
} |
||||
else { |
||||
first = false; |
||||
} |
||||
cout << elem; |
||||
} |
||||
cout << "]\n"; |
||||
|
||||
return 0; |
||||
} |
Loading…
Reference in new issue