- •Вычисления значений
- •Пример:
- •Вычисления типов
- •Преимущества мета подхода:
- •Польза использования mpl:
- •Числовая метафункция
- •Свойства
- •Метаданные
- •Специализация
- •Первичный шаблон:
- •Инстанцирование:
- •Метафункции
- •Полиморфизм
- •Возможности свойств:
- •Организация свойств в Boost:
- •Пример:
- •Типовые ассоциации
- •Альтернатива:
- •Метафункции Продвижение (пересылка) метафункций
- •Класс метафункции
- •Формат:
- •Числовые
- •Пример:
- •Нульарные
- •Метрический анализ (Анализ размерностей)
- •Метрики
- •Величины
- •Сложение и вычитание
- •Умножение
- •Класс метафункции
- •Деление
- •Пример:
- •Метафункции высшего порядка (Каскады вложенных вызовов)
- •Использование apply:
- •Заполнители
- •Безымянный заполнитель:
- •Определение выражений с заполнителями
- •Лямбда (Лямбда метафункции/выражения)
- •Частичное приложение метафункции
- •Лямбда и Шаблоны Неметафункции
- •Обертки
- •Выбор типа
- •Ленивый Выбор Типа
- •Логические Операторы
- •Целочисленные обертки
- •Составные Операторы
- •Операторы с булевым значением:
- •Операторы для сравнения значений:
- •Операторы для интегральных значений:
- •Побитовые операторы:
- •Арифметические операторы:
- •Целочисленная «стенография»
- •Интегральные последовательности
- •Формат:
- •Последовательности
- •Концепции
- •Итераторы
- •Двунаправленные
- •Произвольные
- •Последовательности
- •Двунаправленные
- •Произвольные
- •Расширенные
- •Ассоциативные
- •Требования
- •Расширения
- •Расширенные ассоциативные последовательности
- •Алгоритмы и последовательности
- •Итераторы
- •Равенство
- •Операции Внутренние операции с последовательностей
- •Наследование
- •Создание последовательности
- •Реализация:
- •Создание итератора
- •Преимущества полной специализации перед частичной:
- •Добавление расширения
- •Алгоритмы
- •Абстракция:
- •Stl алгоритмы
- •Детали правильного использования stl:
- •Mpl алгоритмы
- •Различия stl и mpl алгоритмов:
- •Пример:
- •Вставки
- •Пример 1:
- •Пример 2:
- •Пример 3:
- •Фундамент алгоритмов
- •Пример:
- •Запрашиваемые алгоритмы
- •Последовательности (Алгоритмы, создающие последовательности)
- •Синонимы функциональных алгоритмов:
- •Создание алгоритма
- •Итераторы «Просмотр» и итераторы-адаптеры
- •Концепция просмотра
- •Применение просмотра Сравнения значений элементов последовательности:
- •Объединение множественных (мульти-) последовательностей
- •Упрощение 1
- •Упрощение 2 (создание просмотра)
- •Уход от ненужного вычисления
- •Выборочная обработка элемента
- •Итератор-адаптер
- •Создание просмотра
- •Реализация итератора-адаптера для zip_view.
- •Диагностика
- •Отладка ошибок
- •Трассировка инстанцирования
- •Исправленный пример:
- •Форматы сообщений об ошибках
- •Блок «with»
- •Устранение параметров шаблона по умолчанию
- •Глубокий typedef
- •Инструменты
- •Несколько компиляторов
- •(Статические Утверждения)
- •Формат:
- •Формат:
- •Индивидуальные сообщения утверждений
- •Настройка предиката:
- •(Генерирование встроенных сообщений)
- •Формат:
- •Выбор стратегии:
- •Тип печати
- •Кросс этапность компиляции/выполнения
- •Печать типов:
- •Тип посещения:
- •Выбор реализаций
- •Специализация шаблонов классов
- •Тег диспетчеризации
- •Выбор структуры
- •Композиция классов
- •Указатели на функцию
- •Ослабление типизации
- •Пример:
- •Обобщение:
- •Динамический полиморфизм
- •Автоматизация
- •Сохранение интерфейса
- •Рекуррентный шаблон
- •Формат:
- •Генерирование функций
- •Управление разрешением перегрузки
- •Явное управление множеством перегрузки
- •Документация mpl Последовательности
- •Концепции
- •(Прямая последовательность)
- •(Двунаправленная Последовательность)
- •(Последовательность произвольного доступа)
- •(Расширенная последовательность)
- •(Расширенная последовательность начала)
- •(Расширенная последовательность конца)
- •(Ассоциативная последовательность)
- •(Расширенная ассоциативная последовательность)
- •(Обертка интегральной последовательности )
- •(Переменная последовательность)
- •Представления
- •Метафункции (Внутренние)
- •Итераторы
- •Концепции
- •(Прямой итератор)
- •(Двунаправленный итератор)
- •(Итератор произвольного доступа)
- •Метафункции
- •Алгоритмы
- •Концепции
- •(Инсертер: механизм вставок)
- •Инсертеры (инсертер: механизм вставок)
- •Итеративные алгоритмы
- •Запрашиваемые алгоритмы
- •Преобразования
- •Метафункции
- •Концепции Метафункция
- •Метафункциональный класс
- •Лямбда выражения
- •Заполнители
- •Тэг диспетчеризированные метафункции
- •Числовые метафункции
- •Тривиальные метафункции
Упрощение 1
Такое повторение фактически дает подсказку относительно того, как мы могли бы улучшить положение вещей. Мы ищем в последовательности элементов упорядоченной по размерам, сравнивая размер каждого с заданным значением и возвращаем размер найденного. Нас не интересует последовательность самих элементов: мы заботимся только об их размерах.
Так, нужно сделать из последовательности типов соответствующую последовательность размеров и вести поиск в ней, это позволяет использовать предикат c однородным сравнением элементов:
template<class Seq, class MinSize>
struct padded_size
: mpl::deref<
typename mpl::lower_bound<
typename mpl::transform<Seq, mpl::sizeof_<_>>::type, //последовательность размеров
MinSize,
mpl::less<_,_> //однородное сравнение
>::type
>
{};
К тому же, в метафункции mpl::lower_bound по умолчанию используется предикат mpl::less<_, _>, следовательно можно упростить запись до:
template<class Seq, class MinSize>
struct padded_size
: mpl::deref<
typename mpl::lower_bound<
typename mpl::transform<Seq, mpl::sizeof_<_>>::type,
MinSize
>::type
>
{};
Так, в первой версии, сложность последовательного расчета размера типа составляла O(log N) – экспоненциально возрастала с количеством. Во второй версии, сначала расчитывались размеры элементов всей последовательности, после чего, она передавалась в метафункцию mpl::lower_bound.
Проблема: плохая эффективность.
Упрощение 2 (создание просмотра)
Можно объединить лучшее, что есть в двух версиях, создав последовательность просмотра, что позволит определять размеры с помощью ленивого вызова transform_view:
template<class Seq, class MinSize>
struct first_size_larger_than
: mpl::deref<
typename mpl::lower_bound<
mpl::transform_view<Seq, mpl::sizeof_<_>>,
MinSize
>::type
>
{};
Transform_view <S, P> является последовательностью просмотра, элементы которой идентичны элементам transform <S, P>, но с двумя важными различиями:
Элементы вычисляются только «по требованию» - ленивая последовательность.
Каждый итератор последовательности просмотра является адаптером для одного или нескольких базовых итераторов (от базовых последовательностей), для обращения к значениям каждого из базовых итераторов (соответствующей позиции в S), используется вложенный элемент «::base».
zip_view
Объединение множественных (мульти-) последовательностей
Только один алгоритм времени компиляции по созданию последовательностей, mpl::transform, имеет прямую поддержку работы с парами элементов от двух входных последовательностей: появление этого алгоритма обязано желаением сохранить однородность и совместимость подходов с STL. Для других видов операций со множественными последовательностями (три или больше), необходим другой подход.
MPL предоставляет компонент, который позволяет использовать одиночную последовательность, для решения любой проблемы, требующей работы с множеством последовательностей.
Алгоритм zip_view преобразовывает последовательность N-ого количества входных последовательностей в последовательность последовательностей и упорядочивает элементы. Так, если
S [s1, s2, s3...], T [t1, t2, t3...], и U [u1, u2, u3...],
то элементы zip_view <vector <S, T, U>> будут иметь вид
[[s1, t1, u1...], [s2, t2, u2...], [s3, t3, u3...]...].
Например, поэлементная сумма трех векторов могла бы быть записана:
mpl::transform_view<
mpl::zip_view<mpl::vector<V1,V2,V3>>,
mpl::plus<
mpl::at<_, mpl::int_<0>>,
mpl::at<_, mpl::int_<1>>,
mpl::at<_, mpl::int_<2>>
>
>
Это не слишком плохо, но, распаковка векторных элементов с mpl::at является громоздкой и неудобной. Код можно улучшить, используя MPL обертку unpack_args, которая преобразовывает лямбда-выражение с N-ым количеством аргументов наподобии mpl::plus<_, _, _> в унарное лямбда-выражение.
Когда к последовательности из N элементов применяется:
mpl::unpack_args <лямбда-выражение>
то извлекается каждый из элементов последовательности и поочередно передается параметру лямбда-выражение.
Следующая эквивалентная перезапись поэлементной суммы использует unpack_args, чтобы достигнуть существенного улучшения удобочитаемости:
mpl::transform_view<
mpl::zip_view<mpl::vector<V1,V2,V3>>,
mpl::unpack_args<mpl::plus<_,_,_>>
>
