§ 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