Задания по С++ — различия между версиями
Katepol (обсуждение | вклад) (→Лабораторная работа №5 functor) |
Btv (обсуждение | вклад) (→Лабораторная работа №12 метапрограммирование smart_print) |
||
(не показано 7 промежуточных версий 3 участников) | |||
Строка 26: | Строка 26: | ||
== Лабораторная работа №2 Синглтон == | == Лабораторная работа №2 Синглтон == | ||
− | Написать | + | Написать простой логгер |
<source lang="cpp">class Logger { | <source lang="cpp">class Logger { | ||
public: | public: | ||
Строка 59: | Строка 59: | ||
== Лабораторная работа №4 iterator == | == Лабораторная работа №4 iterator == | ||
− | Написать | + | Написать шаблонный класс <code>slist</code> односвязный список.<br /> |
+ | <source lang="cpp">template<typename _Ty> | ||
+ | class slist { | ||
+ | public: | ||
+ | push_back(const _Ty&); | ||
+ | forward begin(); | ||
+ | forward end(); | ||
+ | slist(); | ||
+ | _Ty back() const; | ||
+ | }; | ||
+ | </source> | ||
Реализовать для него <code>forward</code> итератор. | Реализовать для него <code>forward</code> итератор. | ||
− | |||
== Лабораторная работа №5 functor == | == Лабораторная работа №5 functor == | ||
Строка 82: | Строка 91: | ||
mem_fun(&std::set<int>::count)(s, 3); | mem_fun(&std::set<int>::count)(s, 3); | ||
</source> | </source> | ||
− | |||
== Лабораторная работа №7 заполнитель мапы == | == Лабораторная работа №7 заполнитель мапы == | ||
Строка 89: | Строка 97: | ||
std::map<float, int> m(mapper(1.0, 2)(2, 2)(4, 2)); | std::map<float, int> m(mapper(1.0, 2)(2, 2)(4, 2)); | ||
</source> | </source> | ||
+ | |||
+ | == Лабораторная работа №8-9 класс матрицы == | ||
+ | Реализовать класс матрицы MxN (с двумя выделениями памяти).<br/> | ||
+ | Спроектировать его с учётом исключений: безопасный, с декларацией бросаемых исключений. | ||
+ | |||
+ | == Лабораторная работа №10 двойная диспетчерезация == | ||
+ | Иногда в больших системах возникает потребность в некоторой бинарной операции, которая полиморфно зависит от типов обоих аргументов. | ||
+ | |||
+ | Пример: пересечение геометрических примитивов. Мы умеем пересекать круги с кругами, прямоугольники с прямоугольниками и прямоугольники с кругами. Нужно реализовать функцию <code>bool intersects(Shape * a, Shape * b);</code> | ||
+ | |||
+ | Ваше задание: написать механизм, который позволил бы реализовать двойную диспетчеризацию. | ||
+ | |||
+ | Идея механизма: есть некоторый класс, которые отвечает за диспетчеризацию (диспетчер). У него хранится map, который паре <code>typeid</code> сопоставляет класс, реализующий функцию <code>intersects</code>. | ||
+ | В функции <code>intersects</code> у диспетчера запрашивается реализация по паре <code>typeid</code> аргументов. Диспетчер позволяет регистрировать/ | ||
+ | разрегистрировать различные реализации. Если реализации для пересечения двух объектов не нашлось, то функция пересечения кидает исключение. | ||
+ | |||
+ | ''Примечание'': сравнивать объеткы <code>type_info</code> надо с помощью <code>type_info.before(type_info)</code>. | ||
+ | <code>intersects</code> должна быть коммутативна. | ||
+ | |||
+ | == Лабораторная работа №11 операторы new/delete == | ||
+ | Перегрузить глобальные операторы <code>new/delete</code>, <code>new[]/delete[]</code>. | ||
+ | Оптимизировать процедуру веделения/освобождения памяти, например, не очищать память при вызове <code>delete</code>, а кешировать её и отдавать при следующем вызове <code>new</code>. | ||
+ | |||
+ | Попробовать реализованный менеджер памяти в каком-нибудь вашем проекте, сравнить времена работы вашей реализации и дефолтной. | ||
+ | |||
+ | == Лабораторная работа №12 метапрограммирование smart_print == | ||
+ | Реализовать шаблонную функцию | ||
+ | <source lang="cpp"> | ||
+ | template<typename T> | ||
+ | void smart_print(const T& arg); | ||
+ | </source> | ||
+ | которая выводит на печать аргумент. | ||
+ | Если у аргумента есть <code>arg::iterator</code>, то вывести на печать символ начала коллекции, затем проитерироваться по элементам коллекции и вывести их на печать с помощью <code>smart_print</code> и в конце символ конца коллекции. | ||
+ | Иначе просто вывести агрумент на печать. | ||
+ | |||
+ | Результат работы такой функции на списке векторов интов должен выглядить подобным образом | ||
+ | <code>[ [ 1 2 ] [ 3 ] [ 45 32 ] ]</code>. | ||
+ | |||
+ | Для этого необходимо воспользоваться бустовыми <code>BOOST_MPL_HAS_XXX_TRAIT_DEF</code> и <code>enable_if_c/disable_if_c</code>. |
Текущая версия на 20:09, 13 мая 2011
Содержание
- 1 Лабораторная работа №1 Шаблоны
- 2 Лабораторная работа №2 Синглтон
- 3 Лабораторная работа №3 merge sort
- 4 Лабораторная работа №4 iterator
- 5 Лабораторная работа №5 functor
- 6 Лабораторная работа №6 mem_fun
- 7 Лабораторная работа №7 заполнитель мапы
- 8 Лабораторная работа №8-9 класс матрицы
- 9 Лабораторная работа №10 двойная диспетчерезация
- 10 Лабораторная работа №11 операторы new/delete
- 11 Лабораторная работа №12 метапрограммирование smart_print
Лабораторная работа №1 Шаблоны
Реализовать собственный контейнер
template<typename T>
class Container {
public:
void push_back(const T& t);
T& back();
size_t size() const;
};
В качестве хранилища значенией в реализации Container
используйте std::vector
.
Затем создайте новый контейнер с двумя шаблонными параметрами, первый - тип хранимых значений, второй - тип хранилища, используемый в реализации вашего контейнера.
Пример использования такого контейнера
Container<int, std::list<int> > c;
Затем создайте новый контейнер с двумя шаблонными параметрами, первый - тип хранимых значений, второй - шаблон, используемый в реализации вашего контейнера.
Пример использования такого контейнера
Container<int, std::deque> c;
Лабораторная работа №2 Синглтон
Написать простой логгер
class Logger {
public:
void warn(const std::string& msg);
static Logger& getInstance();
};
Запретить пользователю его создание, копирование.
Пример использования
Logger& log = Logger::getInstance();
log.warn("Ooops");
Представить, что понадобилось ещё несколько синглтонов, вынести общий для всех синглтонов код в отдельный класс Singleton
.
Реализовать логгер с использованием класса Singleton
так, чтоб код, использующий логгер, не надо было модифицировать.
Лабораторная работа №3 merge sort
Необходимо написать функцию сортировки слиянием.
Сигнатура функции должны быть такой:
template<typename Iter>
std::list<typename Iter::value_type> mergeSort(Iter left, Iter right);
Исходные данные функция модифицировать не должна, в возвращаемом списке должны быть отсортированные элементы.
Затем необходимо добиться, чтоб можно было сортировать по указателям:
int* array = new int[SIZE];
mergeSort(array, array + SIZE);
Рекомендации: для merge можно воспользоваться std::list::merge
для получения типа, на который указывает указатель, можно воспользоваться std::iterator_traits
Лабораторная работа №4 iterator
Написать шаблонный класс slist
односвязный список.
template<typename _Ty>
class slist {
public:
push_back(const _Ty&);
forward begin();
forward end();
slist();
_Ty back() const;
};
Реализовать для него forward
итератор.
Лабораторная работа №5 functor
Реализовать алгоритм
template<typename InIter, typename OutIter, typename Pred>
OutIter filter(InIter begin, InIter end, OutIter out, Pred pred);
который читает элементы и, если pred(val)
возвращает true
, то записывает элемент в out
.
Реализовать собственный функтор, который принимает std::set<char>
и char
и проверят наличие входного символа в сете.
С помощью алгоритма filter
и вашего функтора отфильровать строку.
Лабораторная работа №6 mem_fun
Реализовать аналог std::mem_fun
, убедиться, что аналог работает на коде:
std::vector<char> v;
std::set<int> s;
mem_fun(&std::vector<char>::push_back)(v, 'd');
mem_fun(&std::set<int>::count)(s, 3);
Лабораторная работа №7 заполнитель мапы
Реализовать заполнитель мапы
std::map<float, int> m(mapper(1.0, 2)(2, 2)(4, 2));
Лабораторная работа №8-9 класс матрицы
Реализовать класс матрицы MxN (с двумя выделениями памяти).
Спроектировать его с учётом исключений: безопасный, с декларацией бросаемых исключений.
Лабораторная работа №10 двойная диспетчерезация
Иногда в больших системах возникает потребность в некоторой бинарной операции, которая полиморфно зависит от типов обоих аргументов.
Пример: пересечение геометрических примитивов. Мы умеем пересекать круги с кругами, прямоугольники с прямоугольниками и прямоугольники с кругами. Нужно реализовать функцию bool intersects(Shape * a, Shape * b);
Ваше задание: написать механизм, который позволил бы реализовать двойную диспетчеризацию.
Идея механизма: есть некоторый класс, которые отвечает за диспетчеризацию (диспетчер). У него хранится map, который паре typeid
сопоставляет класс, реализующий функцию intersects
.
В функции intersects
у диспетчера запрашивается реализация по паре typeid
аргументов. Диспетчер позволяет регистрировать/
разрегистрировать различные реализации. Если реализации для пересечения двух объектов не нашлось, то функция пересечения кидает исключение.
Примечание: сравнивать объеткы type_info
надо с помощью type_info.before(type_info)
.
intersects
должна быть коммутативна.
Лабораторная работа №11 операторы new/delete
Перегрузить глобальные операторы new/delete
, new[]/delete[]
.
Оптимизировать процедуру веделения/освобождения памяти, например, не очищать память при вызове delete
, а кешировать её и отдавать при следующем вызове new
.
Попробовать реализованный менеджер памяти в каком-нибудь вашем проекте, сравнить времена работы вашей реализации и дефолтной.
Лабораторная работа №12 метапрограммирование smart_print
Реализовать шаблонную функцию
template<typename T>
void smart_print(const T& arg);
которая выводит на печать аргумент.
Если у аргумента есть arg::iterator
, то вывести на печать символ начала коллекции, затем проитерироваться по элементам коллекции и вывести их на печать с помощью smart_print
и в конце символ конца коллекции.
Иначе просто вывести агрумент на печать.
Результат работы такой функции на списке векторов интов должен выглядить подобным образом
[ [ 1 2 ] [ 3 ] [ 45 32 ] ]
.
Для этого необходимо воспользоваться бустовыми BOOST_MPL_HAS_XXX_TRAIT_DEF
и enable_if_c/disable_if_c
.