- •Вычисления значений
- •Пример:
- •Вычисления типов
- •Преимущества мета подхода:
- •Польза использования mpl:
- •Числовая метафункция
- •Свойства
- •Метаданные
- •Специализация
- •Первичный шаблон:
- •Инстанцирование:
- •Метафункции
- •Полиморфизм
- •Возможности свойств:
- •Организация свойств в Boost:
- •Пример:
- •Типовые ассоциации
- •Альтернатива:
- •Метафункции Продвижение (пересылка) метафункций
- •Класс метафункции
- •Формат:
- •Числовые
- •Пример:
- •Нульарные
- •Метрический анализ (Анализ размерностей)
- •Метрики
- •Величины
- •Сложение и вычитание
- •Умножение
- •Класс метафункции
- •Деление
- •Пример:
- •Метафункции высшего порядка (Каскады вложенных вызовов)
- •Использование apply:
- •Заполнители
- •Безымянный заполнитель:
- •Определение выражений с заполнителями
- •Лямбда (Лямбда метафункции/выражения)
- •Частичное приложение метафункции
- •Лямбда и Шаблоны Неметафункции
- •Обертки
- •Выбор типа
- •Ленивый Выбор Типа
- •Логические Операторы
- •Целочисленные обертки
- •Составные Операторы
- •Операторы с булевым значением:
- •Операторы для сравнения значений:
- •Операторы для интегральных значений:
- •Побитовые операторы:
- •Арифметические операторы:
- •Целочисленная «стенография»
- •Интегральные последовательности
- •Формат:
- •Последовательности
- •Концепции
- •Итераторы
- •Двунаправленные
- •Произвольные
- •Последовательности
- •Двунаправленные
- •Произвольные
- •Расширенные
- •Ассоциативные
- •Требования
- •Расширения
- •Расширенные ассоциативные последовательности
- •Алгоритмы и последовательности
- •Итераторы
- •Равенство
- •Операции Внутренние операции с последовательностей
- •Наследование
- •Создание последовательности
- •Реализация:
- •Создание итератора
- •Преимущества полной специализации перед частичной:
- •Добавление расширения
- •Алгоритмы
- •Абстракция:
- •Stl алгоритмы
- •Детали правильного использования stl:
- •Mpl алгоритмы
- •Различия stl и mpl алгоритмов:
- •Пример:
- •Вставки
- •Пример 1:
- •Пример 2:
- •Пример 3:
- •Фундамент алгоритмов
- •Пример:
- •Запрашиваемые алгоритмы
- •Последовательности (Алгоритмы, создающие последовательности)
- •Синонимы функциональных алгоритмов:
- •Создание алгоритма
- •Итераторы «Просмотр» и итераторы-адаптеры
- •Концепция просмотра
- •Применение просмотра Сравнения значений элементов последовательности:
- •Объединение множественных (мульти-) последовательностей
- •Упрощение 1
- •Упрощение 2 (создание просмотра)
- •Уход от ненужного вычисления
- •Выборочная обработка элемента
- •Итератор-адаптер
- •Создание просмотра
- •Реализация итератора-адаптера для zip_view.
- •Диагностика
- •Отладка ошибок
- •Трассировка инстанцирования
- •Исправленный пример:
- •Форматы сообщений об ошибках
- •Блок «with»
- •Устранение параметров шаблона по умолчанию
- •Глубокий typedef
- •Инструменты
- •Несколько компиляторов
- •(Статические Утверждения)
- •Формат:
- •Формат:
- •Индивидуальные сообщения утверждений
- •Настройка предиката:
- •(Генерирование встроенных сообщений)
- •Формат:
- •Выбор стратегии:
- •Тип печати
- •Кросс этапность компиляции/выполнения
- •Печать типов:
- •Тип посещения:
- •Выбор реализаций
- •Специализация шаблонов классов
- •Тег диспетчеризации
- •Выбор структуры
- •Композиция классов
- •Указатели на функцию
- •Ослабление типизации
- •Пример:
- •Обобщение:
- •Динамический полиморфизм
- •Автоматизация
- •Сохранение интерфейса
- •Рекуррентный шаблон
- •Формат:
- •Генерирование функций
- •Управление разрешением перегрузки
- •Явное управление множеством перегрузки
- •Документация mpl Последовательности
- •Концепции
- •(Прямая последовательность)
- •(Двунаправленная Последовательность)
- •(Последовательность произвольного доступа)
- •(Расширенная последовательность)
- •(Расширенная последовательность начала)
- •(Расширенная последовательность конца)
- •(Ассоциативная последовательность)
- •(Расширенная ассоциативная последовательность)
- •(Обертка интегральной последовательности )
- •(Переменная последовательность)
- •Представления
- •Метафункции (Внутренние)
- •Итераторы
- •Концепции
- •(Прямой итератор)
- •(Двунаправленный итератор)
- •(Итератор произвольного доступа)
- •Метафункции
- •Алгоритмы
- •Концепции
- •(Инсертер: механизм вставок)
- •Инсертеры (инсертер: механизм вставок)
- •Итеративные алгоритмы
- •Запрашиваемые алгоритмы
- •Преобразования
- •Метафункции
- •Концепции Метафункция
- •Метафункциональный класс
- •Лямбда выражения
- •Заполнители
- •Тэг диспетчеризированные метафункции
- •Числовые метафункции
- •Тривиальные метафункции
Пример 1:
Вставка, которая строит новый вектор может выглядеть так:
mpl::inserter<mpl::vector<>, mpl::push_back<_,_>>
где mpl::inserter определяется как:
template <class State, class Operation>
struct inserter
{
typedef State state;
typedef Operation operation;
};
Работа вставки основана на операциях подобных push_back и push_front с подобнымие именами и назначением: back_inserter и front_inserter.
mpl::back_inserter<mpl::vector<>>
Пример 2:
Использование вставок в STL для алгоритма std::copy:
std::vector<any> v; // start with empty vector
std::copy(start, finish, std::back_inserter(v));
Версия mpl::copy принимает входящую последовательность вместо пары итераторов как в STL версии:
typedef mpl::copy
<
mpl::list<A, B, C>,
mpl::back_inserter<mpl::vector<>>
>::type result_vec;
На каждом шаге алгоритма, бинарная операция вставки вызывается с результатом предыдущего шага (на первом шаге используется исходный тип) в качестве первого аргумента, и элемент, который, как правило, записывается в выходной итератор в качестве второго аргумента. Алгоритм возвращает результат последнего шага:
typedef
mpl::push_back< // >----------------+
// |
mpl::push_back< // >--------------+ |
// | |
mpl::push_back< // >------------+ | |
mpl::vector<> // | | |
, A // | | |
>::type // first step <-+ | |
, B // | |
>::type // second step <--+ |
, C // |
>::type // third step <-----+
result_vec;
MPL поддерживает вставки по умолчанию для всех алгоритмов, создающих последовательностями (именно поэтому мы смогли использовать mpl::transform, без явного указания вставки.).
Пример 3:
Использование вставки для суммирования элементов разных последовательностей друг с другом.
typedef mpl::vector<
mpl::vector_c<int, 1, 2, 3>,
mpl::vector_c<int, 4, 5, 6>,
mpl::vector_c<int, 7, 8, 9>
> S;
typedef mpl::transform<
S, // input sequence
mpl::front<_>, // transformation selects front element (вернет 1 элемент)
mpl::inserter<
mpl::int_<0>, // result starts with 0
mpl::plus<_,_> // and adds each output element
>
>::type sum; // 0 + 1 + 4 + 7 == 12
Без вставки, transform будет строить вектор, состоящий из первоначальных элементов каждой последовательности в S; при использовании вставки, эти начальные элементы передаются в mpl::plus<_,_>, начиная со значения mpl::int_<0>.
Фундамент алгоритмов
В основе работы алгоритмов подобных back_inserter лежит паттерн «сворачивания» элементов входящей последовательности в результирующую.
Данный паттерн является ядром обработки всех последовательностей в функциональной среде и реализовывается метафункциями «*_fold».
Является фундаментальной функциональной абстракцией, которая повторяет применение бинарной функции к элементам и последовательности и «накапливает» результирующее значение, используя результат функции на каждом шаге, как дополнительное значение для следующего шага. STL содержит подобную абстракцию под названием accumulate.
MPL обобщает реализацю fold двумя способами: для работы с элементами последовательности или их значениями, с помощью (iter_fold) а таже, обеспечивая двунаправленный обхода (reverse_ [iter_] fold).
fold
Псевдокод:
fold(Seq, Prev, BinaryOp) :=
if Seq is empty then:
Prev
else: // combine the first element with Prev
fold( // and process the rest recursively
tail(Seq), // оставить хвост последовательности
BinaryOp(Prev, head(Seq)), // обработка Prev и головы
BinaryOp
)
Prev, вероятно, следует назвать InitialType. На каждом этапе обработки, кроме первого, Prev является результатом предыдущего шага обработки.
Можно создать много других, более сложных последовательностей обхода алгоритмов используя логику mpl::fold для раскрутки последовательности (достаточно выполнить наследование).
Например, можно разворачивать любые последовательности, поддерживающие расширения front_*:
template <class Seq>
struct reverse
: mpl::fold<
Seq,
typename mpl::clear<Seq>::type, // initial type - чистая последовательность равной длины
mpl::push_front<_,_> // binary operation: push_front(ячейка чистой Seq, элемент Seq)
>
{};
