Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions 2025-2026/Week 14/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ _Бонус_:

_Бонус_:
* or_else - ако съдържа стойност, връща самият обект, иначе връща резултат от подадена функция
* and_then - ако съдържа стойност, връща резултата от подадена функция,иначе връща празен обект
* transform - ако съдържа стойност, връща обект съдържащ резултата от подадена функция, иначе връща празен обект
* and_then - ако съдържа стойност, връща резултата от подадена функция, изпълнена върху стойността, иначе връща празен обект
* transform - ако съдържа стойност, връща обект съдържащ резултата от подадена функция, изпълнена върху стойността, иначе връща празен обект

**Задача 3:**

Expand Down
198 changes: 198 additions & 0 deletions 2025-2026/Week 14/Solutions/include/Either.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
#pragma once

#include <functional>
#include <utility>

template <class Left, class Right>
class Either {
Left* leftValue;
Right* rightValue;
bool isLeft;

void copy(const Either &other);

void move(Either &&other) noexcept;

void free();

public:
Either(const Left &left);
Either(const Right &right);

Either(Left &&left);
Either(Right &&right);

Either(const Either &other);
Either(Either &&other) noexcept;
Either &operator=(const Either &other);
Either &operator=(Either &&other) noexcept;

bool is_left() const;
bool is_right() const;

Left &left() &;
const Left &left() const&;
Left&& left() &&;

Right &right() &;
const Right &right() const&;
Right &&right() &&;

template <class U>
Either<U, Right> transform_left(const std::function<U(const Left &)> &f) const;

template <class U>
Either<Left, U> transform_right(const std::function<U(const Right &)> &f) const;

template <class U>
Either<U, Right> and_then(const std::function<Either<U, Right>(const Left &)> &f) const;

template <class U, class V>
Either<U, V> visit(const std::function<U(const Left &)> &left,
const std::function<V(const Right &)> &right);
};

template <class Left, class Right>
template <class U, class V>
Either<U, V> Either<Left, Right>::visit(const std::function<U(const Left &)> &left, const std::function<V(const Right &)> &right) {
if (is_left())
return left(this->left());
else
return right(this->right());
}

template <class Left, class Right>
template <class U>
Either<U, Right> Either<Left, Right>::and_then(const std::function<Either<U, Right>(const Left &)> &f) const {
if (is_left())
return f(left());
else
return Either<U, Right>(right());
}

template <class Left, class Right>
template <class U>
Either<Left, U> Either<Left, Right>::transform_right(const std::function<U(const Right &)> &f) const {
if (is_left())
return Either<Left, U>(left());
else
return Either<Left, U>(f(right()));
}

template <class Left, class Right>
template <class U>
Either<U, Right> Either<Left, Right>::transform_left(const std::function<U(const Left &)> &f) const {
if (is_left())
return Either<U, Right>(f(left()));
else
return Either<U, Right>(right());
}

template <class Left, class Right>
void Either<Left, Right>::copy(const Either &other) {
isLeft = other.isLeft;
if (isLeft) {
leftValue = new Left(other.left());
rightValue = nullptr;
}
else {
rightValue = new Right(other.right());
leftValue = nullptr;
}
}
template <class Left, class Right>
void Either<Left, Right>::move(Either &&other) noexcept{
std::swap(isLeft, other.isLeft);
std::swap(leftValue, other.leftValue);
std::swap(rightValue, other.rightValue);
}
template <class Left, class Right> void Either<Left, Right>::free() {
if (isLeft) {
delete leftValue;
}
else {
delete rightValue;
}
}
template <class Left, class Right>
Either<Left, Right>::Either(const Left &left)
: leftValue(new Left(left)), rightValue(nullptr), isLeft(true) {}

template <class Left, class Right>
Either<Left, Right>::Either(const Right &right)
: leftValue(nullptr), rightValue(new Right(right)), isLeft(false) {}

template <class Left, class Right>
Either<Left, Right>::Either(Left &&left)
: leftValue(new Left(std::move(left))), rightValue(nullptr), isLeft(true) {}

template <class Left, class Right>
Either<Left, Right>::Either(Right &&right)
: leftValue(nullptr), rightValue(new Right(std::move(right))), isLeft(false) {}

template <class Left, class Right>
Either<Left, Right>::Either(const Either &other) {
copy(other);
}

template <class Left, class Right>
Either<Left, Right>::Either(Either &&other) noexcept {
move(std::move(other));
}

template <class Left, class Right>
Either<Left, Right> &Either<Left, Right>::operator=(const Either &other) {
if (this != &other) {
free();
copy(other);
}
return *this;
}
template <class Left, class Right>
Either<Left, Right> &Either<Left, Right>::operator=(Either &&other) noexcept {
if (this != &other) {
free();
move(std::move(other));
}
return *this;
}

template <class Left, class Right>
bool Either<Left, Right>::is_left() const {
return isLeft;
}

template <class Left, class Right>
bool Either<Left, Right>::is_right() const {
return !isLeft;
}

template <class Left, class Right>
const Left &Either<Left, Right>::left() const& {
return *leftValue;
}

template <class Left, class Right>
Left &Either<Left, Right>::left() &{
return *leftValue;
}

template <class Left, class Right>
const Right &Either<Left, Right>::right() const& {
return *rightValue;
}

template <class Left, class Right>
Right &Either<Left, Right>::right() &{
return *rightValue;
}

template <class Left, class Right>
Left &&Either<Left, Right>::left() &&{
return std::move(*leftValue);
}

template <class Left, class Right>
Right &&Either<Left, Right>::right() &&{
return std::move(*rightValue);
}
184 changes: 184 additions & 0 deletions 2025-2026/Week 14/Solutions/include/Optional.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
#pragma once
#include <functional>
#include <utility>

template<class T>
class Optional{
T* data;
bool empty;

void copy(const Optional &other);

void move(Optional &&other) noexcept;

void free();

public:
Optional();
Optional(const T &data);
Optional(T &&data);
Optional(const Optional &other);
Optional(Optional &&other) noexcept;
Optional &operator=(const Optional &other);
Optional &operator=(Optional &&other) noexcept;
~Optional();

bool has_value() const;

T &value() &;
const T &value() const&;
T &&value() &&;



T &operator*() &;
const T &operator*() const&;
T &&operator*() &&;

const T *operator->() const;
T *operator->();

T value_or(const T &fallback) const;

Optional<T> or_else(const std::function<Optional<T>()> &fallback) const;

template <class U>
Optional<U> and_then(const std::function<Optional<U>(const T &)> &f) const;

template <class U>
Optional<U> transform(const std::function<U(const T &)> &f) const;
};

template <class T>
template <class U>
Optional<U> Optional<T>::transform(const std::function<U(const T &)> &f) const {
if (has_value())
return Optional<U>(f(value()));
else
return Optional<U>();
}

template <class T>
template <class U>
Optional<U> Optional<T>::and_then(const std::function<Optional<U>(const T &)> &f) const {
if (has_value())
return f(value());
else
return Optional<U>();
}

template <class T>
void Optional<T>::copy(const Optional &other) {
if (other.has_value()) {
empty = false;
data = new T(other.value());
} else {
empty = true;
data = nullptr;
}
}

template <class T>
void Optional<T>::move(Optional &&other) noexcept {
data = other.data;
empty = other.empty;

other.data = nullptr;
other.empty = true;
}
template <class T>
void Optional<T>::free() {
delete data;
empty = true;
}

template <class T>
Optional<T>::Optional() : data(nullptr), empty(true) {}

template <class T>
Optional<T>::Optional(const T &data) : data(new T(data)), empty(false) {}

template <class T>
Optional<T>::Optional(T &&data) : data(new T(std::move(data))), empty(false) {}

template <class T>
Optional<T>::Optional(const Optional &other) {
copy(other);
}

template <class T>
Optional<T>::Optional(Optional &&other) noexcept {
move(std::move(other));
}

template <class T>
Optional<T> &Optional<T>::operator=(const Optional &other) {
if (this == &other)
return *this;
free();
copy(other);
return *this;
}

template <class T>
Optional<T>& Optional<T>::operator=(Optional &&other) noexcept {
if (this == &other)
return *this;
free();
move(std::move(other));
return *this;
}

template <class T>
Optional<T>::~Optional() { free(); }

template <class T>
bool Optional<T>::has_value() const { return !empty; }

template <class T>
const T &Optional<T>::value() const& { return *data; }

template <class T>
T &Optional<T>::value() & { return *data; }

template <class T>
T &&Optional<T>::value() && { return std::move(*data); }

template <class T>
const T &Optional<T>::operator*() const& {
return value();
}

template <class T>
T &Optional<T>::operator*() & {
return value();
}

template <class T>
T &&Optional<T>::operator*() && {
return std::move(value());
}

template <class T>
const T *Optional<T>::operator->() const {
return data;
}

template <class T>
T *Optional<T>::operator->() { return data; }

template <class T>
T Optional<T>::value_or(const T &fallback) const {
if (has_value())
return value();
else
return fallback;
}

template <class T>
Optional<T> Optional<T>::or_else(const std::function<Optional<T>()> &fallback) const {
if (has_value())
return *this;
else
return fallback();
};
Loading