§ 15. Дополнительные задания

Задание 1

01Создайте простой модульный тест для каждого из следующих методов класса std::string:

string(const string&)
string(string&&)
string& operator=(const string&)
string& operator=(string&&)

Описание модульных тестов есть в задании 2.

Задание 2

02Перед выполнением заданий скопируйте исходный код программы, используя следующие команды.

git clone https://courses.igankevich.com/system-programming/sha1.git
cd sha1
meson build
cd build
ninja
./src/sha1/sha1

Напишите модульные тесты для функций sha1::put и sha1::compute и доведите уровень покрытия тестами этих функций до 100% по веткам кода. Под ветками кода здесь понимаются ветки кода в ассемблере: if (x && y) генерирует четыре ветки кода (количество строк в таблице истинности логического И). Из-за ограничений компилятора в строчках, где выбрасываются исключения, одна из веток останется неохваченной; этот дефект мы игнорируем, но в тестах все равно должны проверяться все исключения. На финальную цифру отчета внимания можно не обращать, поскольку она дается для всей программы, а не для наших двух функций. Покрытие будет полным, когда в HTML-отчете во всех колонках слева будут плюсы, кроме строчек с исключениями. Для генерации отчета о покрытии тестами, используйте следующие команды.

meson configure -Db_coverage=true # включить запись данных
ninja test                        # запустить тесты, чтобы собрать данные
ninja coverage-html               # сгенерировать HTML-отчет

Примеры входных и выходных значений для этой кодировки есть на странице Википедии.

Задание 3

03Реализуйте все методы в следующем прототипе класса по аналогии с классом std::vector. Все конструкторы и оператор присваивания должны использовать метод swap.

template <class T>
class Array {
private:
    std::unique_ptr<T[]> _elements;
    size_t _size = 0;
public:
    Array() = default;
    ~Array() = default;
    Array(const Array& rhs);
    Array(Array&& rhs) noexcept;
    Array& operator=(const Array& rhs);
    Array& operator=(Array&& rhs);
    void push_back(const T& value);
    void push_back(T&& value);
    void erase(T* position);
    size_t size() const noexcept;
    T& operator[](size_t index) noexcept;
    const T& operator[](size_t index) const noexcept;
    T* begin() noexcept;
    T* end() noexcept;
    const T* begin() const noexcept;
    const T* end() const noexcept;
    void swap(Array& other) noexcept;
};
template <class T>
inline void swap(Array<T>& a, Array<T>& b) noexcept { a.swap(b); }

Напишите модульный тесты для проверки работы следующих методов: push_back, erase, operator=. Вы можете добавить дополнительные публичные методы для написания тестов, а также любые приватные методы, которые сочтете необходимыми для реализации публичных.

Задание 4

04Реализуйте функцию call, которая вызывает указанную в первом аргументе функцию с аргументами из кортежа:

template <class Function, class ... Args>
auto call(Function func, std::tuple<Args&&...> args);

// пример
call([] (int x, int y) { return x+y; }, std::forward_as_tuple(1,2)); // 3

Реализация должна работать для количества аргументов от 0 до 3.

Задание 5

05Возьмите код из задания 6 и добавьте к нему выражение Map, которое применяет функцию к каждому элементу другого выражения. Роль функции-конструктора для этого выражения играет функция map:

Vector<float> a{1,2,3};
Vector<float> b = evaluate(map(a, [] (float elem) { return elem*2; }));
// 2 4 6