Website Summary Files Commits Branches @commit @diff @stats
path: root / Week11
diff options
context:
space:
mode:
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/>