Re-did the constructors for the vector class
This commit is contained in:
parent
f8efc21ff6
commit
2edac15430
12
README.org
12
README.org
@ -2,15 +2,17 @@
|
|||||||
|
|
||||||
* P’undrak’s STL
|
* P’undrak’s STL
|
||||||
|
|
||||||
This is my very own partial, sketchy, weird and ineffective STL implementation, mainly focused around the containers of the actual Standard Template Library. You have absolutely no other reason to look at this source code than being a student like myself seeking for hints on how to do things. Spoiler: what you will see here is probably not the right way to do it, but hey, it works!
|
This is my very own partial, sketchy, weird and ineffective STL implementation, mainly focused on the containers of the actual Standard Template Library. You have absolutely no other reason to look at this source code than being a student like myself seeking for hints on how to do things. Spoiler: what you will see here is probably not the right way to do it, but hey, it works!... sometimes. I also try to stay as close as possible to the C++17 standard. I might not always follow it though.
|
||||||
|
|
||||||
Developped under Spacemacs, compiled with Clang++, debugged with GDB and DDD, and drinking milk. Yeah, I don’t like coffee. Milk though...
|
Developped under Spacemacs, compiled with Clang++, debugged with GDB, drinking milk. Yeah, I don’t like coffee. Milk though...
|
||||||
|
|
||||||
|
Also, don’t pay any attention to [[https://github.com/Phundrak/PhundrakSTL/blob/master/src/test.cc][src/test.cc]], it is just me testing my STL and fooling around with it.
|
||||||
|
|
||||||
* Installation
|
* Installation
|
||||||
|
|
||||||
Haha, good joke.
|
Haha, good joke!
|
||||||
|
|
||||||
Seriously, if you want to use it, just download the header files, place them in your include directory in your project, and add them with ~#include "vector.hh"~ or something like that. But honestly, use it only for testing purposes, not for actual work. That would be a terrible idea.
|
Seriously, if you want to use it, just download the header files, place them in your include directory in your project, and add them with ~#include "vector.hh"~ or something like that. But honestly, use it only for testing purposes, or looking at how I did things, but not for actual work. That would be a terrible idea.
|
||||||
|
|
||||||
* Licence
|
* Licence
|
||||||
|
|
||||||
@ -19,3 +21,5 @@ See the LICENCE.md file, basically you are free to do whatever you want with my
|
|||||||
* Bugs
|
* Bugs
|
||||||
|
|
||||||
Yep, there are bugs. I may or may not fix them, it’s up to me.
|
Yep, there are bugs. I may or may not fix them, it’s up to me.
|
||||||
|
|
||||||
|
Also, Github doesn’t seem to fully recognize org-mode’s syntax. Well...
|
||||||
|
@ -68,21 +68,21 @@ namespace phundrak {
|
|||||||
}
|
}
|
||||||
|
|
||||||
list(size_type count, const T &value, const Allocator &alloc = Allocator())
|
list(size_type count, const T &value, const Allocator &alloc = Allocator())
|
||||||
: list(alloc), alloc_{alloc} {
|
: list{alloc} {
|
||||||
while (size() < count)
|
while (size() < count)
|
||||||
push_back(value);
|
push_back(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit list(size_type count, const Allocator &alloc = Allocator())
|
explicit list(size_type count, const Allocator &alloc = Allocator())
|
||||||
: list(alloc), alloc_{alloc} {
|
: list{alloc} {
|
||||||
while (size() < count)
|
while (size() < count)
|
||||||
push_back(T());
|
push_back(T());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class InputIt>
|
template <class InputIt>
|
||||||
list(InputIt first, InputIt last, const Allocator &alloc = Allocator())
|
list(InputIt first, InputIt last, const Allocator &alloc = Allocator())
|
||||||
: list(alloc) {
|
: list{alloc} {
|
||||||
while (first != last)
|
for (;first != last; ++first)
|
||||||
push_back(*first);
|
push_back(*first);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
25
src/test.cc
25
src/test.cc
@ -2,11 +2,31 @@
|
|||||||
#include "vector.hh"
|
#include "vector.hh"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
using namespace phundrak;
|
using phundrak::list;
|
||||||
|
using phundrak::vector;
|
||||||
using std::cout;
|
using std::cout;
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
|
|
||||||
|
cout << "\n\nTest vecteur\n";
|
||||||
|
|
||||||
|
vector<char> testvec;
|
||||||
|
testvec.push_back('C');
|
||||||
|
testvec.push_back('a');
|
||||||
|
testvec.push_back('r');
|
||||||
|
testvec.push_back('t');
|
||||||
|
testvec.push_back('i');
|
||||||
|
testvec.push_back('e');
|
||||||
|
testvec.push_back('r');
|
||||||
|
|
||||||
|
for(size_t i = 0; i < testvec.size(); ++i) {
|
||||||
|
cout << testvec[i] << " ";
|
||||||
|
}
|
||||||
|
cout << std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
cout << "\n\nTest list\n";
|
||||||
|
|
||||||
list<char> test{'C', 'a', 'r', 't', 'i', 'e', 'r'};
|
list<char> test{'C', 'a', 'r', 't', 'i', 'e', 'r'};
|
||||||
|
|
||||||
for (auto c : test)
|
for (auto c : test)
|
||||||
@ -14,7 +34,8 @@ int main(void) {
|
|||||||
|
|
||||||
cout << "\n";
|
cout << "\n";
|
||||||
|
|
||||||
list<int> test_unique {1,1,1,1,1,2,2,2,3,3,3,4,4,1,1,5,1,2,1,1,3,3,3};
|
list<int> test_unique{1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4,
|
||||||
|
4, 1, 1, 5, 1, 2, 1, 1, 3, 3, 3};
|
||||||
printf("Elements before unique():\n");
|
printf("Elements before unique():\n");
|
||||||
for (const auto &elem : test_unique)
|
for (const auto &elem : test_unique)
|
||||||
cout << elem << " ";
|
cout << elem << " ";
|
||||||
|
170
src/vector.hh
170
src/vector.hh
@ -1,41 +1,127 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <memory>
|
|
||||||
#include <iterator>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <iterator>
|
||||||
|
#include <memory>
|
||||||
|
#include <stdexcept>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
namespace phundrak {
|
namespace phundrak {
|
||||||
|
using size_type = size_t;
|
||||||
|
|
||||||
|
template <class T, class Allocator = std::allocator<T>> class vector {
|
||||||
|
|
||||||
|
private:
|
||||||
|
void double_capacity() {
|
||||||
|
if (data_) {
|
||||||
|
T *olddata = data_;
|
||||||
|
capacity_ <<= 1;
|
||||||
|
data_ = new T[capacity_];
|
||||||
|
for (size_t i = 0; i < size_; ++i)
|
||||||
|
data_[i] = olddata[i];
|
||||||
|
delete[] olddata;
|
||||||
|
} else {
|
||||||
|
data_ = new T[1];
|
||||||
|
capacity_ = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
T *data_;
|
||||||
|
size_t size_;
|
||||||
|
size_t capacity_;
|
||||||
|
Allocator alloc_;
|
||||||
|
|
||||||
template<class T>
|
|
||||||
class vector {
|
|
||||||
public:
|
public:
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Member functions //
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Member functions ///////////////////////////////////////////////////////
|
// constructor ////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//! Default constructor
|
vector() noexcept(noexcept(Allocator()))
|
||||||
vector() : data_{nullptr}, size_{0}, capacity_{0} {}
|
: vector{Allocator()} {}
|
||||||
|
|
||||||
|
explicit vector(const Allocator &alloc) noexcept
|
||||||
|
: data_{nullptr}, size_{0}, capacity_{0}, alloc_{alloc} {}
|
||||||
|
|
||||||
|
vector(size_type count, const T &value, const Allocator &alloc = Allocator())
|
||||||
|
: vector{alloc}, data_{nullptr}, size_{0}, capacity_{0} {
|
||||||
|
for (size_t i = 0; i < count; ++i)
|
||||||
|
push_back(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit vector(size_type count, const Allocator &alloc = Allocator())
|
||||||
|
: data_{nullptr}, size_{0}, capacity_{0}, alloc_{alloc} {
|
||||||
|
for (size_type i = 0; i < count; ++i)
|
||||||
|
push_back(T{});
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class InputIt>
|
||||||
|
vector(InputIt first, InputIt last, const Allocator &alloc = Allocator())
|
||||||
|
: data_{nullptr}, size_{0}, capacity_{0}, alloc_{alloc} {
|
||||||
|
for (; first != last; ++first)
|
||||||
|
push_back(*first);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy constructor ///////////////////////////////////////////////////////
|
||||||
|
|
||||||
//! Copy constructor
|
|
||||||
vector(const vector<T> &other)
|
vector(const vector<T> &other)
|
||||||
: data_{new T[other.size_]}, size_{other.size_},
|
: data_{new T[other.size_]}, size_{other.size_},
|
||||||
capacity_{other.capacity_} {
|
capacity_{other.capacity_}, alloc_{other.alloc_} {
|
||||||
for (size_t i = 0; i < size_; ++i) {
|
if (!alloc_) {
|
||||||
|
alloc_ = std::allocator_traits<Allocator>::
|
||||||
|
select_on_container_copy_construction(other.get_allocator());
|
||||||
|
}
|
||||||
|
for (size_type i = 0; i < size_; ++i)
|
||||||
data_[i] = other.data_[i];
|
data_[i] = other.data_[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vector(const vector &other, const Allocator &alloc)
|
||||||
|
: data_{new T[other.size_]}, size_{other.size},
|
||||||
|
capacity_{other.capacity_}, alloc_{alloc} {
|
||||||
|
try {
|
||||||
|
if (alloc_ != other.alloc_)
|
||||||
|
throw 20;
|
||||||
|
} catch (int error) {
|
||||||
|
std::cout << "Error in phundrak::vector(const vector &other, const "
|
||||||
|
"Allocator &alloc) :\nThe allocator "
|
||||||
|
<< alloc
|
||||||
|
<< " passed as argument is different from other’s allocator "
|
||||||
|
<< other.alloc_ << "\nAborting...\n";
|
||||||
|
std::terminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Move constructor
|
for (size_type i = 0; i < size_; ++i)
|
||||||
|
data_[i] = other.data_[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move constructor ///////////////////////////////////////////////////////
|
||||||
|
|
||||||
vector(vector<T> &&other) noexcept {
|
vector(vector<T> &&other) noexcept {
|
||||||
std::swap(data_, other.data_);
|
std::swap(data_, other.data_);
|
||||||
std::swap(size_, other.size_);
|
std::swap(size_, other.size_);
|
||||||
std::swap(capacity_, other.capacity_);
|
std::swap(capacity_, other.capacity_);
|
||||||
|
std::swap(alloc_, other.alloc_);
|
||||||
|
}
|
||||||
|
|
||||||
|
vector(vector &&other, const Allocator &alloc) {
|
||||||
|
if (alloc != other.alloc_) {
|
||||||
|
capacity_ = other.capacity_;
|
||||||
|
size_ = other.size_;
|
||||||
|
data_ = new T[capacity_];
|
||||||
|
alloc_ = alloc;
|
||||||
|
for (size_type i = 0; i < size_; ++i) {
|
||||||
|
data_[i] = std::move(other.data_[i]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::swap(capacity_, other.capacity);
|
||||||
|
std::swap(size_, other.size);
|
||||||
|
std::swap(data_, other.data_);
|
||||||
|
std::swap(alloc_, other.alloc_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Destructor
|
//! Destructor
|
||||||
virtual ~vector() noexcept {
|
virtual ~vector() noexcept { delete[] data_; }
|
||||||
delete[] data_;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Copy assignment operator
|
//! Copy assignment operator
|
||||||
vector &operator=(const vector<T> &other) {
|
vector &operator=(const vector<T> &other) {
|
||||||
@ -65,17 +151,16 @@ namespace phundrak {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename InputIt,
|
template <typename InputIt,
|
||||||
typename std::enable_if_t<!std::is_integral<InputIt>::value, InputIt>* = nullptr>
|
typename std::enable_if_t<!std::is_integral<InputIt>::value,
|
||||||
|
InputIt> * = nullptr>
|
||||||
|
void assign(InputIt first, InputIt last) {
|
||||||
// template <class InputIt> void assign(InputIt first, InputIt last) {
|
clear();
|
||||||
// clear();
|
capacity_ = std::distance(first, last);
|
||||||
// capacity_ = std::distance(first, last);
|
size_ = capacity_;
|
||||||
// size_ = std::distance(first, last);
|
data_ = new T[capacity_];
|
||||||
// data_ = new T[size_];
|
for (int i = 0; first != last, i < size_; ++first, ++i)
|
||||||
// for (int i = 0; first != last; ++first, ++i)
|
data_[i] = *first;
|
||||||
// data_[i] = *first;
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
// Element access /////////////////////////////////////////////////////////
|
// Element access /////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@ -94,7 +179,7 @@ namespace phundrak {
|
|||||||
try {
|
try {
|
||||||
if (pos >= size_ || pos < 0)
|
if (pos >= size_ || pos < 0)
|
||||||
throw std::out_of_range("Out of range");
|
throw std::out_of_range("Out of range");
|
||||||
} catch (std::out_of_range e) {
|
} catch (const std::out_of_range &e) {
|
||||||
std::cout << e.what() << " in phundrak::vector " << this << '\n';
|
std::cout << e.what() << " in phundrak::vector " << this << '\n';
|
||||||
std::terminate();
|
std::terminate();
|
||||||
}
|
}
|
||||||
@ -120,9 +205,7 @@ namespace phundrak {
|
|||||||
|
|
||||||
// Capacity ///////////////////////////////////////////////////////////////
|
// Capacity ///////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
bool empty() const noexcept {
|
bool empty() const noexcept { return (data_ == nullptr) ? true : false; }
|
||||||
return (data_ == nullptr) ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t size() const noexcept { return size_; }
|
size_t size() const noexcept { return size_; }
|
||||||
|
|
||||||
@ -189,31 +272,6 @@ namespace phundrak {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
void double_capacity() {
|
|
||||||
if(data_) {
|
|
||||||
T *olddata = data_;
|
|
||||||
capacity_ <<= 1;
|
|
||||||
data_ = new T[capacity_];
|
|
||||||
for(size_t i = 0; i < size_; ++i)
|
|
||||||
data_[i] = olddata[i];
|
|
||||||
delete[] olddata;
|
|
||||||
} else {
|
|
||||||
data_ = new T[1];
|
|
||||||
capacity_ = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
T * data_;
|
|
||||||
size_t size_;
|
|
||||||
size_t capacity_;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace phundrak
|
||||||
|
|
||||||
} // phundrak namespace
|
|
||||||
|
Loading…
Reference in New Issue
Block a user