Re-did the constructors for the vector class

This commit is contained in:
Phuntsok Drak-pa 2017-10-22 01:17:55 +02:00
parent f8efc21ff6
commit 2edac15430
4 changed files with 293 additions and 210 deletions

View File

@ -2,15 +2,17 @@
* Pundraks STL * Pundraks 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 dont like coffee. Milk though... Developped under Spacemacs, compiled with Clang++, debugged with GDB, drinking milk. Yeah, I dont like coffee. Milk though...
Also, dont 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, its up to me. Yep, there are bugs. I may or may not fix them, its up to me.
Also, Github doesnt seem to fully recognize org-modes syntax. Well...

View File

@ -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);
} }

View File

@ -2,26 +2,47 @@
#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) {
list<char> test {'C', 'a', 'r', 't', 'i', 'e', 'r'}; cout << "\n\nTest vecteur\n";
for(auto c : test) 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'};
for (auto c : test)
cout << c << " "; cout << c << " ";
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 << " ";
cout << "\n"; cout << "\n";
test_unique.unique(); test_unique.unique();
for(const auto& elem : test_unique) for (const auto &elem : test_unique)
cout << elem << " "; cout << elem << " ";
cout << "\n"; cout << "\n";

View File

@ -1,44 +1,130 @@
#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> template <class T, class Allocator = std::allocator<T>> class vector {
class vector {
public:
// Member functions /////////////////////////////////////////////////////// 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;
}
}
//! Default constructor T *data_;
vector() : data_{nullptr}, size_{0}, capacity_{0} {} size_t size_;
size_t capacity_;
Allocator alloc_;
public:
///////////////////////////////////////////////////////////////////////////
// Member functions //
///////////////////////////////////////////////////////////////////////////
// constructor ////////////////////////////////////////////////////////////
vector() noexcept(noexcept(Allocator()))
: 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 others 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) {
vector<T> w{other}; vector<T> w{other};
std::swap(data_, w.data_); std::swap(data_, w.data_);
std::swap(size_, w.size_); std::swap(size_, w.size_);
@ -64,18 +150,17 @@ namespace phundrak {
push_back(value); push_back(value);
} }
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 /////////////////////////////////////////////////////////
@ -83,7 +168,7 @@ namespace phundrak {
try { try {
if (pos >= size_) if (pos >= size_)
throw std::out_of_range("Out of range"); throw std::out_of_range("Out of range");
} catch (const 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();
} }
@ -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_; }
@ -182,38 +265,13 @@ namespace phundrak {
push_back(value); push_back(value);
} }
void swap(vector<T>& other) { void swap(vector<T> &other) {
std::swap(capacity_, other.capacity_); std::swap(capacity_, other.capacity_);
std::swap(size_, other.size_); std::swap(size_, other.size_);
std::swap(data_, other.data_); std::swap(data_, other.data_);
} }
protected: protected:
};
} // namespace phundrak
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_;
};
} // phundrak namespace