#ifndef CONTACT_LIST_HPP #define CONTACT_LIST_HPP #include namespace MyStructures { template class ContactList { public: /** * Contains an array of Contacts or othe C class objects */ ContactList() = default; ContactList(size_t length); //Creates contact list of this size ContactList(const C* contacts, const size_t& length, const size_t size); //Makes a copy of another contact list ContactList(const C* storage, const size_t& length); ~ContactList(); ContactList(const ContactList& copy); //deep copy constructor ContactList& operator=(const ContactList& rhs); //deep copy assignment ContactList(ContactList&& move); //reference(move) constructor ContactList& operator=(ContactList&& rhs); //reference(move) assignment void Print() const; //Print the Contact List, calling Print on each element. size_t Size() const; //Return the size of the contact list void Append(const C& data); //Add contact to back of list void Prepend(const C& data); //add contact as first contact void RemoveLast(); //removes last contact void RemoveFirst(); //removes first contact void Extract(const C& data); //delete this contact: data void InsertAfter(const C& data, const C& after); //insert contact data after 'after' contact void InsertBefore(const C& data, const C& before); //insert contact data before 'before' contact void Clear(); //Deletes all contacts, empties the list, nothing left! void ContactDelete(const size_t& elementNumber); C& Last(); //returns last contact reference in list C Last() const; //returns copy of last contact in list C& First(); //returns first contact reference in lsit C First() const; //returns first contact copy C& operator[](const int& index); //returns contact reference via [] overload C operator[](const int& index) const; //returns contact copy via [] overload explicit operator bool() const; // overloads ContactList to return to true/false as boolean operator bool operator==(const ContactList& rhs) const; //if (newContact == old Contact) bool Empty() const; //is the list empty bool Full() const; //returns true if all allocated private: C* contacts_{ nullptr }; size_t length_{ 0 }; //entire length of array size_t size_{ 0 }; //number of actual numbers C* AllocateContactList(const size_t& length); }; template void ContactList::ContactDelete(const size_t& elementNumber) { size_t index = elementNumber; contacts_[index].Delete(); } template ContactList::ContactList(const C* contacts, const size_t& length) { contacts_ = AllocateContactList(length); for (auto i = 0u; i < length_; ++i) { contacts_[i] = contacts[i]; } } template inline ContactList::ContactList(size_t length) { } template ContactList::ContactList(const C* contacts, const size_t& length, const size_t size) { contacts_ = AllocateContactList(length); for (auto i = 0u; i < length_; ++i) { contacts_[i] = contacts[i]; } } template ContactList::~ContactList() { delete[] contacts_; contacts_ = nullptr; } template ContactList::ContactList(const ContactList& copy) { delete[] contacts_; contacts_ = nullptr; auto temp = ContactList{ copy.contacts_, copy.length_ }; *this = std::move(temp); size_ = copy.size_; } template ContactList& ContactList::operator=(const ContactList& rhs) { if (this != &rhs) { delete[] contacts_; contacts_ = nullptr; auto temp = ContactList{ rhs.contacts_, rhs.length_ }; *this = std::move(temp); size_ = rhs.size_; } return *this; } template ContactList::ContactList(ContactList&& move) { *this = std::move(move); } template ContactList& ContactList::operator=(ContactList&& rhs) noexcept { if (this != &rhs) { delete[] contacts_; contacts_ = nullptr; contacts_ = rhs.contacts_; length_ = rhs.length_; size_ = rhs.size_; rhs.contacts_ = nullptr; } return *this; } template void ContactList::Print() const { for (auto i = 0u; i < length_; ++i) { contacts_[i].Print(); } } template size_t ContactList::Size() const { return size_; } template void ContactList::Append(const C& data) { index = size_; contacts_[index] = data; size_++; return; // whatifs; //whatif: end of the array is the beginning //whatif: in the body of the array if (size_ >= length_) { index = size_; } if (size_ == 0) { contacts_[index] = data; size_++; return; } //whatif: end of the array //length_ == 10; // size_ ==10 // contacts_[10] is out of bounds! //whatif: array is full if (size_ >= length_) { //increase size of array ContactList newContacts(contacts_, length_ * 2); *this = newContacts } // Add to end of the array contacts_[index] = data; size_++; return; } template void ContactList::Prepend(const C& data) { if (Empty()) { if(contacts_ == nullptr) { } Append(data); return; } if (!Full()) { for (int i = static_cast (size_)-1; i >= 0; i--) { contacts_[i + 1] = contacts_[i]; } contacts_[0] = data; return; } auto temp = ContactList(length_); temp.Append(data); for (auto i = 0; i < size_ ++i) { temp.Append(contacts_[i]); } delete[] contacts_; contacts_ = nullptr; *this = std::move(temp); } template void ContactList::RemoveLast() { if (Empty()) return; ContactDelete(size_ - 1); size_--; } template void ContactList::RemoveFirst() { if (Empty()) return; ContactDelete(0); size_--; } template void ContactList::Extract(const C& data) { for (size_t i = 0; i < size_; ++i;) { if (contacts_[i] == data) { for (size_t j = i; j < size_ - 1; ++j) { } ContactDelete(size_t - 1); size_--; return; } } } template inline void ContactList::InsertAfter(const C& data, const C& after) { for (size_t i = 0; i < size_; ++i) { if (contacts_[i] == after) { if (size_ >= length_) { ContactList newContacts(length_ * 2); newContacts.size_ = size_; for (size_t j = 0; j < i + 1; ++j) { newContacts.contacts_[j] = contacts_[j]; } newContacts.contacts_[i + 1] = data; for (size_t j = i + 2; j < newContacts.size_; ++j) { newContacts.contacts_[j] = contacts_[j - 1]; } *this = std::move(newContacts); } else { for (size_t j = size_; j > i + 1; --j) { contacts_[j] = contacts_[j - 1]; } contacts_[i + 1] = data; size_++; } return; } } } template inline void ContactList::InsertBefore(const C& data, const C& before) { for (size_t i = 0; i < size_; ++i) { if (contacts_[i] == before) { if (size_ >= length_) { ContactList newContacts(length_ * 2); newContacts.size_ = size_; for (size_t j = 0; j < i; ++j) { newContacts.contacts_[j] = contacts_[j]; } newContacts.contacts_[i] = data; for (size_t j = i + 1; j < newContacts.size_; ++j) { newContacts.contacts_[j] = contacts_[j - 1]; } *this = std::move(newContacts); } else { for (size_t j = size_; j > i; --j) { contacts_[j] = contacts_[j - 1]; } contacts_[i] = data; size_++; } return; } } } template void ContactList::Clear() { size_ = 0; length_ = 0; delete[] contacts_; contacts_ = nullptr; } template C& ContactList::Last() { return contacts_[size_]; } template C ContactList::Last() const { return contacts_[size_ - 1]; } template C& ContactList::First() { return contacts_[size_ - 1]; } template C ContactList::First() const { return contacts_[0]; } template C& ContactList::operator[](const int& index) { if (index < 0 || index >= static_cast(length_)) { Contact emptyContact; std::cerr << "The index exceeds the array length" << endl; return emptyContact; } return contacts_[index]; } template C ContactList::operator[](const int& index) const { if (index < 0 || index >= static_cast(size_)) { cerr << "The index exceeds the array length" << endl; return NULL;; } return contacts_[index]; } template ContactList::operator bool() const { bool var = contacts_ != nullptr; return (var); //if(addressBook) } template bool ContactList::operator==(const ContactList& rhs) const { //Performance //shortcut easy ways of knowing the same if (contacts_ == rhs.contacts_)return true; if (size_ != rhs.size_)return false; if (length_ != rhs.length_)return false; //if those fields are equivalent, then check every value for (auto i = 0u; i < size_; ++i) { if (contacts_[i] != rhs.contacts_[i]) return false; } return true; } template bool ContactList::Empty() const { return size_ == 0; } template bool ContactList::Full() const { if (size_ < length_) return false; return true; } template C* ContactList::AllocateContactList(const size_t& length) { C* storage = nullptr; length_ = length; storage = new C[length]{}; return storage; } }; #endif