diff options
12 files changed, 783 insertions, 0 deletions
| -rw-r--r-- | Week11/Exercise01/Pair.hpp | 43 | ||||
| -rw-r--r-- | Week11/Exercise02/Option.hpp | 68 | ||||
| -rw-r--r-- | Week11/Exercise02/main.cpp | 25 | ||||
| -rw-r--r-- | Week11/Exercise03/SharedPointer.hpp | 129 | ||||
| -rw-r--r-- | Week11/Exercise03/main.cpp | 17 | ||||
| -rw-r--r-- | Week11/Exercise04/Vector.hpp | 147 | ||||
| -rw-r--r-- | Week11/Exercise04/main.cpp | 23 | ||||
| -rw-r--r-- | Week11/Exercise05/DoubleVector.hpp | 201 | ||||
| -rw-r--r-- | Week11/Exercise05/Pair.hpp | 43 | ||||
| -rw-r--r-- | Week11/Exercise06/UniquePointer.hpp | 75 | ||||
| -rw-r--r-- | Week11/Exercise06/main.cpp | 9 | ||||
| -rw-r--r-- | Week11/README.md | 3 |
diff --git a/Week11/Exercise01/Pair.hpp b/Week11/Exercise01/Pair.hpp new file mode 100644 index 0000000..4fd47fd --- /dev/null +++ b/Week11/Exercise01/Pair.hpp @@ -0,0 +1,43 @@ +#ifndef _PAIR +#define _PAIR + +template<class T, class U> +class Pair { + T left; + U right; + +public: + Pair(const T& left, const U& right); + + T& Left(); + const T& Left() const; + + U& Right(); + const U& Right() const; +}; + +template<class T, class U> +Pair<T, U>::Pair(const T& left, const U& right) : left(left), right(right) +{ } + +template<class T, class U> +T& Pair<T, U>::Left() { + return left; +} + +template<class T, class U> +const T& Pair<T, U>::Left() const { + return left; +} + +template<class T, class U> +U& Pair<T, U>::Right() { + return right; +} + +template<class T, class U> +const U& Pair<T, U>::Right() const { + return right; +} + +#endif /* _PAIR */ diff --git a/Week11/Exercise02/Option.hpp b/Week11/Exercise02/Option.hpp new file mode 100644 index 0000000..69f7297 --- /dev/null +++ b/Week11/Exercise02/Option.hpp @@ -0,0 +1,68 @@ +#ifndef _OPTION +#define _OPTION + +template <class T> +class Option { + T obj; + bool isSomething; + + Option(); +public: + static Option Some(T value); + static Option None(); + + bool IsSome() const; + bool IsNone() const; + T Unwrap(); +}; + +template <class T> +Option<T>::Option() : obj(), isSomething(false) +{ } + +template <class T> +Option<T> Option<T>::Some(T value) { + Option op; + op.isSomething = true; + op.obj = value; + return op; +} + +// Какво запазваме, когато искаме да запазим нищо? +// Ако работехме с T*, щяхме да запазим nullptr. +// В нашия случай, няма голямо значение каква е стойността на obj, +// затова просто ще запазим стойността по подразбиране. +// Ако съответния тип няма конструктор по подразбиране, тогава ще +// получим грешка по време на компилация. +template <class T> +Option<T> Option<T>::None() { + return Option(); +} + +template <class T> +bool Option<T>::IsSome() const { + return isSomething; +} + +template <class T> +bool Option<T>::IsNone() const { + return !isSomething; +} + +// Както при None метода, тук е нужно T да има имплементиран +// копиращи и/или преместващи семантики (конструктор и operator=). +// +// Обаче, ако ние сме създали обект чрез None, тогава Unwrap ще ни +// върне потенциално валидна стойност: тази по подразбиране. +// Коректното решение тук е да имаме проверка за isSomething, +// и ако не е, да "хвърлим грешка". Но това още не сме го учили. +// +// За момента ще приемем, че ако програмист направи Unwrap на обект, +// създаден чрез None, тогава това е негов пропуск, който сам трябва +// да си оправи. +template <class T> +T Option<T>::Unwrap() { + return obj; +} + +#endif /* _OPTION */ diff --git a/Week11/Exercise02/main.cpp b/Week11/Exercise02/main.cpp new file mode 100644 index 0000000..f734373 --- /dev/null +++ b/Week11/Exercise02/main.cpp @@ -0,0 +1,25 @@ +#include "Option.hpp" +#include <cmath> +#include <iostream> + +Option<double> trySqrt(double x) { + if (x < 0.0) + return Option<double>::None(); + return Option<double>::Some(sqrt(x)); +} + +int main() { + double num; + std::cin >> num; + + Option<double> numRoot = trySqrt(num); + + if (numRoot.IsSome()) { + std::cout << numRoot.Unwrap() << std::endl; + } + else { + std::cout << "Couldn't find square root!" << std::endl; + } + + return 0; +} diff --git a/Week11/Exercise03/SharedPointer.hpp b/Week11/Exercise03/SharedPointer.hpp new file mode 100644 index 0000000..06f9bbb --- /dev/null +++ b/Week11/Exercise03/SharedPointer.hpp @@ -0,0 +1,129 @@ +#ifndef _SHAREDPOINTER +#define _SHAREDPOINTER + +template<class T> +class SharedPointer { + T* value; + unsigned* instances; + + void free(); + void copyFrom(const SharedPointer& other); + +public: + SharedPointer(T* value); + + SharedPointer(); + ~SharedPointer(); + SharedPointer(const SharedPointer& other); + SharedPointer& operator=(const SharedPointer& other); + + SharedPointer(SharedPointer&& other); + SharedPointer& operator=(SharedPointer&& other); + + T& operator*(); + const T& operator*() const; + T* operator->(); + const T* operator->() const; + + unsigned RefCount() const; +}; + +template <class T> +void SharedPointer<T>::free() { + if (instances == nullptr) + return; + + --*instances; + if (*instances == 0) { + delete instances; + delete value; + } +} + +template <class T> +void SharedPointer<T>::copyFrom(const SharedPointer& other) { + this->instances = other.instances; + this->value = other.value; + ++*instances; +} + +template <class T> +SharedPointer<T>::SharedPointer(T* value) : instances(new unsigned), value(value) +{ + *instances = 1; +} + +template <class T> +SharedPointer<T>::SharedPointer() : instances(), value() +{ } + +template <class T> +SharedPointer<T>::~SharedPointer() { + free(); +} + +template <class T> +SharedPointer<T>::SharedPointer(const SharedPointer& other) { + copyFrom(other); +} + +template <class T> +SharedPointer<T>& SharedPointer<T>::operator=(const SharedPointer& other) { + if (this != &other) { + free(); + copyFrom(other); + } + return *this; +} + +template <class T> +SharedPointer<T>::SharedPointer(SharedPointer&& other) { + instances = other.instances; + value = other.value; + + other.instances = nullptr; + other.value = nullptr; +} + +template <class T> +SharedPointer<T>& SharedPointer<T>::operator=(SharedPointer&& other) { + if (this != &other) { + free(); + + instances = other.instances; + value = other.value; + + other.instances = nullptr; + other.value = nullptr; + } + return *this; +} + +template <class T> +T& SharedPointer<T>::operator*() { + return *value; +} + +template <class T> +const T& SharedPointer<T>::operator*() const { + return *value; +} + +template <class T> +T* SharedPointer<T>::operator->() { + return value; +} + +template <class T> +const T* SharedPointer<T>::operator->() const { + return value; +} + +template <class T> +unsigned SharedPointer<T>::RefCount() const { + if (instances == nullptr) + return 0; + return *instances; +} + +#endif /* _SHAREDPOINTER */ diff --git a/Week11/Exercise03/main.cpp b/Week11/Exercise03/main.cpp new file mode 100644 index 0000000..d8a4d66 --- /dev/null +++ b/Week11/Exercise03/main.cpp @@ -0,0 +1,17 @@ +#include "SharedPointer.hpp" +#include <iostream> + +void inc(SharedPointer<int> val) { + (*val)++; +} + +int main() { + SharedPointer<int> x(new int); + SharedPointer<int> y = x; + *x = 5; + std::cout << *x << ' ' << *y << std::endl; + inc(y); + std::cout << *x << ' ' << *y << std::endl; + + return 0; +} diff --git a/Week11/Exercise04/Vector.hpp b/Week11/Exercise04/Vector.hpp new file mode 100644 index 0000000..78dba08 --- /dev/null +++ b/Week11/Exercise04/Vector.hpp @@ -0,0 +1,147 @@ +#ifndef _VECTOR +#define _VECTOR + +template<class T> +class Vector { + T* objects; + unsigned objectsCount; + unsigned objectsAlloc; + + void free(); + void copyFrom(const Vector& other); + + void resize(); + +public: + Vector(); + ~Vector(); + Vector(const Vector& other); + Vector& operator=(const Vector& other); + + Vector(Vector&& other); + Vector& operator=(Vector&& other); + + unsigned Count() const; + void PushBack(const T& object); + + T& operator[](unsigned index); + const T& operator[](unsigned index) const; + + Vector& operator+=(const Vector& rhs); +}; + +template<class T> +Vector<T> operator+(const Vector<T>& lhs, const Vector<T>& rhs); + +template<class T> +void Vector<T>::free() { + delete[] objects; +} + +template<class T> +void Vector<T>::copyFrom(const Vector& other) { + objectsCount = other.objectsCount; + objectsAlloc = other.objectsAlloc; + + objects = new T[objectsAlloc]; + for (unsigned i = 0; i < objectsCount; ++i) + objects[i] = other.objects[i]; +} + +template<class T> +void Vector<T>::resize() { + objectsAlloc = objectsAlloc == 0 ? 8 : objectsAlloc * 2; + T* objectsLarger = new T[objectsAlloc]; + + for (unsigned i = 0; i < objectsCount; ++i) + objectsLarger[i] = objects[i]; + + delete[] objects; + objects = objectsLarger; +} + +template<class T> +Vector<T>::Vector() : objects(), objectsAlloc(), objectsCount() +{ } + +template<class T> +Vector<T>::~Vector() { + free(); +} + +template<class T> +Vector<T>::Vector(const Vector& other) { + copyFrom(other); +} + +template<class T> +Vector<T>& Vector<T>::operator=(const Vector& other) { + if (this != &other) { + free(); + copyFrom(other); + } + return *this; +} + +template<class T> +Vector<T>::Vector(Vector&& other) { + objects = other.objects; + objectsCount = other.objectsCount; + objectsAlloc = other.objectsAlloc; + + other.objects = nullptr; + other.objectsCount = other.objectsAlloc = 0; +} + +template<class T> +Vector<T>& Vector<T>::operator=(Vector&& other) { + if (this != &other) { + free(); + + objects = other.objects; + objectsCount = other.objectsCount; + objectsAlloc = other.objectsAlloc; + + other.objects = nullptr; + other.objectsCount = other.objectsAlloc = 0; + } + return *this; +} + +template<class T> +unsigned Vector<T>::Count() const { + return objectsCount; +} + +template<class T> +void Vector<T>::PushBack(const T& object) { + if (objectsCount >= objectsAlloc) + resize(); + objects[objectsCount++] = object; +} + +template<class T> +T& Vector<T>::operator[](unsigned index) { + return objects[index]; +} + +template<class T> +const T& Vector<T>::operator[](unsigned index) const { + return objects[index]; +} + +template<class T> +Vector<T>& Vector<T>::operator+=(const Vector& rhs) { + for (unsigned i = 0; i < rhs.objectsCount; ++i) + PushBack(rhs.objects[i]); + return *this; +} + +template<class T> +Vector<T> operator+(const Vector<T>& lhs, const Vector<T>& rhs) { + Vector val(lhs); + val += rhs; + return val; +} + +#endif /* _VECTOR */ diff --git a/Week11/Exercise04/main.cpp b/Week11/Exercise04/main.cpp new file mode 100644 index 0000000..cdf3555 --- /dev/null +++ b/Week11/Exercise04/main.cpp @@ -0,0 +1,23 @@ +#include "Vector.hpp" +#include <iostream> + +void print(const Vector<int> numbers) { + for (unsigned i = 0; i < numbers.Count(); ++i) + std::cout << numbers[i] << ' '; + std::cout << std::endl; +} + +int main() { + Vector<int> nums; + nums.PushBack(1); + nums.PushBack(2); + nums.PushBack(3); + + Vector<int> numsMore(nums); + numsMore.PushBack(4); + numsMore.PushBack(5); + + print(nums + numsMore); + + return 0; +} diff --git a/Week11/Exercise05/DoubleVector.hpp b/Week11/Exercise05/DoubleVector.hpp new file mode 100644 index 0000000..7ffe26c --- /dev/null +++ b/Week11/Exercise05/DoubleVector.hpp @@ -0,0 +1,201 @@ +#ifndef _DOUBLEVECTOR +#define _DOUBLEVECTOR + +#include "Pair.hpp" + +template<class T, class U> +class DoubleVector { + T* first; + unsigned firstCount; + unsigned firstAlloc; + + T* second; + unsigned secondCount; + unsigned secondAlloc; + + void free(); + void copyFrom(const DoubleVector& other); + + void firstResize(); + void secondResize(); + +public: + DoubleVector(); + ~DoubleVector(); + DoubleVector(const DoubleVector& other); + DoubleVector& operator=(const DoubleVector& other); + + DoubleVector(DoubleVector&& other); + DoubleVector& operator=(DoubleVector&& other); + + Pair<unsigned, unsigned> Count() const; + + void FirstPushBack(const T& object); + void SecondPushBack(const U& object); + + Pair<T&, U&> operator[](unsigned index); + const Pair<T&, U&> operator[](unsigned index) const; + + DoubleVector& operator+=(const DoubleVector& rhs); +}; + +template<class T, class U> +DoubleVector<T, U> operator+(const DoubleVector<T, U>& lhs, const DoubleVector<T, U>& rhs); + +template<class T, class U> +void DoubleVector<T, U>::free() { + delete[] first; + delete[] second; +} + +template<class T, class U> +void DoubleVector<T, U>::copyFrom(const DoubleVector& other) { + firstCount = other.firstCount; + firstAlloc = other.firstAlloc; + + first = new T[firstAlloc]; + for (unsigned i = 0; i < firstCount; ++i) + first[i] = other.first[i]; + + secondCount = other.secondCount; + secondAlloc = other.secondAlloc; + + second = new T[secondAlloc]; + for (unsigned i = 0; i < secondCount; ++i) + second[i] = other.second[i]; +} + +template<class T, class U> +void DoubleVector<T, U>::firstResize() { + firstAlloc = firstAlloc == 0 ? 8 : firstAlloc * 2; + T* firstLarger = new T[firstAlloc]; + + for (unsigned i = 0; i < firstCount; ++i) + firstLarger[i] = first[i]; + + delete[] first; + first = firstLarger; +} + +template<class T, class U> +void DoubleVector<T, U>::secondResize() { + secondAlloc = secondAlloc == 0 ? 8 : secondAlloc * 2; + U* secondLarger = new U[secondAlloc]; + + for (unsigned i = 0; i < secondCount; ++i) + secondLarger[i] = second[i]; + + delete[] second; + second = secondLarger; +} + +template<class T, class U> +DoubleVector<T, U>::DoubleVector() + : first(), firstAlloc(), firstCount(), + second(), secondAlloc(), secondCount() +{ } + +template<class T, class U> +DoubleVector<T, U>::~DoubleVector() { + free(); +} + +template<class T, class U> +DoubleVector<T, U>::DoubleVector(const DoubleVector& other) { + copyFrom(other); +} + +template<class T, class U> +DoubleVector<T, U>& DoubleVector<T, U>::operator=(const DoubleVector& other) { + if (this != &other) { + free(); + copyFrom(other); + } + return *this; +} + +template<class T, class U> +DoubleVector<T, U>::DoubleVector(DoubleVector&& other) { + first = other.first; + firstCount = other.firstCount; + firstAlloc = other.firstAlloc; + + second = other.second; + secondCount = other.secondCount; + secondAlloc = other.secondAlloc; + + other.first = nullptr; + other.firstCount = other.firstAlloc = 0; + + other.second = nullptr; + other.secondCount = other.secondAlloc = 0; +} + +template<class T, class U> +DoubleVector<T, U>& DoubleVector<T, U>::operator=(DoubleVector&& other) { + if (this != &other) { + free(); + + first = other.first; + firstCount = other.firstCount; + firstAlloc = other.firstAlloc; + + second = other.second; + secondCount = other.secondCount; + secondAlloc = other.secondAlloc; + + other.first = nullptr; + other.firstCount = other.firstAlloc = 0; + + other.second = nullptr; + other.secondCount = other.secondAlloc = 0; + } + return *this; +} + +template<class T, class U> +Pair<unsigned, unsigned> DoubleVector<T, U>::Count() const { + return Pair(firstCount, secondCount); +} + +template<class T, class U> +void DoubleVector<T, U>::FirstPushBack(const T& object) { + if (firstCount >= firstAlloc) + firstResize(); + first[firstCount++] = object; +} + +template<class T, class U> +void DoubleVector<T, U>::SecondPushBack(const U& object) { + if (secondCount >= secondAlloc) + secondResize(); + second[secondCount++] = object; +} + +template<class T, class U> +Pair<T&, U&> DoubleVector<T, U>::operator[](unsigned index) { + return Pair(first[index], second[index]); +} + +template<class T, class U> +const Pair<T&, U&> DoubleVector<T, U>::operator[](unsigned index) const { + return Pair(first[index], second[index]); +} + +template<class T, class U> +DoubleVector<T, U>& DoubleVector<T, U>::operator+=(const DoubleVector& rhs) { + for (unsigned i = 0; i < rhs.firstCount; ++i) + FirstPushBack(rhs.first[i]); + for (unsigned i = 0; i < rhs.secondCount; ++i) + SecondPushBack(rhs.second[i]); + return *this; +} + +template<class T, class U> +DoubleVector<T, U> operator+(const DoubleVector<T, U>& lhs, const DoubleVector<T, U>& rhs) { + DoubleVector val(lhs); + val += rhs; + return val; +} + +#endif /* _DOUBLEVECTOR */ diff --git a/Week11/Exercise05/Pair.hpp b/Week11/Exercise05/Pair.hpp new file mode 100644 index 0000000..4fd47fd --- /dev/null +++ b/Week11/Exercise05/Pair.hpp @@ -0,0 +1,43 @@ +#ifndef _PAIR +#define _PAIR + +template<class T, class U> +class Pair { + T left; + U right; + +public: + Pair(const T& left, const U& right); + + T& Left(); + const T& Left() const; + + U& Right(); + const U& Right() const; +}; + +template<class T, class U> +Pair<T, U>::Pair(const T& left, const U& right) : left(left), right(right) +{ } + +template<class T, class U> +T& Pair<T, U>::Left() { + return left; +} + +template<class T, class U> +const T& Pair<T, U>::Left() const { + return left; +} + +template<class T, class U> +U& Pair<T, U>::Right() { + return right; +} + +template<class T, class U> +const U& Pair<T, U>::Right() const { + return right; +} + +#endif /* _PAIR */ diff --git a/Week11/Exercise06/UniquePointer.hpp b/Week11/Exercise06/UniquePointer.hpp new file mode 100644 index 0000000..fe95234 --- /dev/null +++ b/Week11/Exercise06/UniquePointer.hpp @@ -0,0 +1,75 @@ +#ifndef _UNIQUEPOINTER +#define _UNIQUEPOINTER + +template<class T> +class UniquePointer { + T* value; + +public: + UniquePointer(T* value); + + UniquePointer(); + ~UniquePointer(); + + UniquePointer(UniquePointer&& other); + UniquePointer& operator=(UniquePointer&& other); + + T& operator*(); + const T& operator*() const; + T* operator->(); + const T* operator->() const; +}; + +template<class T> +UniquePointer<T>::UniquePointer(T* value) : value(value) +{ } + +template<class T> +UniquePointer<T>::UniquePointer() : value() +{ } + +template<class T> +UniquePointer<T>::~UniquePointer() { + delete value; +} + +template<class T> +UniquePointer<T>::UniquePointer(UniquePointer&& other) { + value = other.value; + + other.value = nullptr; +} + +template<class T> +UniquePointer<T>& UniquePointer<T>::operator=(UniquePointer&& other) { + if (this != &other) { + delete value; + + value = other.value; + + other.value = nullptr; + } + return *this; +} + +template<class T> +T& UniquePointer<T>::operator*() { + return *value; +} + +template<class T> +const T& UniquePointer<T>::operator*() const { + return *value; +} + +template<class T> +T* UniquePointer<T>::operator->() { + return value; +} + +template<class T> +const T* UniquePointer<T>::operator->() const { + return value; +} + +#endif /* _UNIQUEPOINTER */ diff --git a/Week11/Exercise06/main.cpp b/Week11/Exercise06/main.cpp new file mode 100644 index 0000000..8853a90 --- /dev/null +++ b/Week11/Exercise06/main.cpp @@ -0,0 +1,9 @@ +#include "UniquePointer.hpp" +#include <utility> + +int main() { + UniquePointer<int> ptr(new int); + // Този ред, без "std::move", ще хвърли грешка, + // понеже нямаме копиращи семантики + UniquePointer<int> ptr1 = std::move(ptr); +} diff --git a/Week11/README.md b/Week11/README.md new file mode 100644 index 0000000..22e82b0 --- /dev/null +++ b/Week11/README.md @@ -0,0 +1,3 @@ +# Задачи + +<https://syndamia.com/teaching/oop-2025/week11/> |
