- •Вычисления значений
- •Пример:
- •Вычисления типов
- •Преимущества мета подхода:
- •Польза использования mpl:
- •Числовая метафункция
- •Свойства
- •Метаданные
- •Специализация
- •Первичный шаблон:
- •Инстанцирование:
- •Метафункции
- •Полиморфизм
- •Возможности свойств:
- •Организация свойств в Boost:
- •Пример:
- •Типовые ассоциации
- •Альтернатива:
- •Метафункции Продвижение (пересылка) метафункций
- •Класс метафункции
- •Формат:
- •Числовые
- •Пример:
- •Нульарные
- •Метрический анализ (Анализ размерностей)
- •Метрики
- •Величины
- •Сложение и вычитание
- •Умножение
- •Класс метафункции
- •Деление
- •Пример:
- •Метафункции высшего порядка (Каскады вложенных вызовов)
- •Использование apply:
- •Заполнители
- •Безымянный заполнитель:
- •Определение выражений с заполнителями
- •Лямбда (Лямбда метафункции/выражения)
- •Частичное приложение метафункции
- •Лямбда и Шаблоны Неметафункции
- •Обертки
- •Выбор типа
- •Ленивый Выбор Типа
- •Логические Операторы
- •Целочисленные обертки
- •Составные Операторы
- •Операторы с булевым значением:
- •Операторы для сравнения значений:
- •Операторы для интегральных значений:
- •Побитовые операторы:
- •Арифметические операторы:
- •Целочисленная «стенография»
- •Интегральные последовательности
- •Формат:
- •Последовательности
- •Концепции
- •Итераторы
- •Двунаправленные
- •Произвольные
- •Последовательности
- •Двунаправленные
- •Произвольные
- •Расширенные
- •Ассоциативные
- •Требования
- •Расширения
- •Расширенные ассоциативные последовательности
- •Алгоритмы и последовательности
- •Итераторы
- •Равенство
- •Операции Внутренние операции с последовательностей
- •Наследование
- •Создание последовательности
- •Реализация:
- •Создание итератора
- •Преимущества полной специализации перед частичной:
- •Добавление расширения
- •Алгоритмы
- •Абстракция:
- •Stl алгоритмы
- •Детали правильного использования stl:
- •Mpl алгоритмы
- •Различия stl и mpl алгоритмов:
- •Пример:
- •Вставки
- •Пример 1:
- •Пример 2:
- •Пример 3:
- •Фундамент алгоритмов
- •Пример:
- •Запрашиваемые алгоритмы
- •Последовательности (Алгоритмы, создающие последовательности)
- •Синонимы функциональных алгоритмов:
- •Создание алгоритма
- •Итераторы «Просмотр» и итераторы-адаптеры
- •Концепция просмотра
- •Применение просмотра Сравнения значений элементов последовательности:
- •Объединение множественных (мульти-) последовательностей
- •Упрощение 1
- •Упрощение 2 (создание просмотра)
- •Уход от ненужного вычисления
- •Выборочная обработка элемента
- •Итератор-адаптер
- •Создание просмотра
- •Реализация итератора-адаптера для zip_view.
- •Диагностика
- •Отладка ошибок
- •Трассировка инстанцирования
- •Исправленный пример:
- •Форматы сообщений об ошибках
- •Блок «with»
- •Устранение параметров шаблона по умолчанию
- •Глубокий typedef
- •Инструменты
- •Несколько компиляторов
- •(Статические Утверждения)
- •Формат:
- •Формат:
- •Индивидуальные сообщения утверждений
- •Настройка предиката:
- •(Генерирование встроенных сообщений)
- •Формат:
- •Выбор стратегии:
- •Тип печати
- •Кросс этапность компиляции/выполнения
- •Печать типов:
- •Тип посещения:
- •Выбор реализаций
- •Специализация шаблонов классов
- •Тег диспетчеризации
- •Выбор структуры
- •Композиция классов
- •Указатели на функцию
- •Ослабление типизации
- •Пример:
- •Обобщение:
- •Динамический полиморфизм
- •Автоматизация
- •Сохранение интерфейса
- •Рекуррентный шаблон
- •Формат:
- •Генерирование функций
- •Управление разрешением перегрузки
- •Явное управление множеством перегрузки
- •Документация mpl Последовательности
- •Концепции
- •(Прямая последовательность)
- •(Двунаправленная Последовательность)
- •(Последовательность произвольного доступа)
- •(Расширенная последовательность)
- •(Расширенная последовательность начала)
- •(Расширенная последовательность конца)
- •(Ассоциативная последовательность)
- •(Расширенная ассоциативная последовательность)
- •(Обертка интегральной последовательности )
- •(Переменная последовательность)
- •Представления
- •Метафункции (Внутренние)
- •Итераторы
- •Концепции
- •(Прямой итератор)
- •(Двунаправленный итератор)
- •(Итератор произвольного доступа)
- •Метафункции
- •Алгоритмы
- •Концепции
- •(Инсертер: механизм вставок)
- •Инсертеры (инсертер: механизм вставок)
- •Итеративные алгоритмы
- •Запрашиваемые алгоритмы
- •Преобразования
- •Метафункции
- •Концепции Метафункция
- •Метафункциональный класс
- •Лямбда выражения
- •Заполнители
- •Тэг диспетчеризированные метафункции
- •Числовые метафункции
- •Тривиальные метафункции
Альтернатива:
Добавление пользовательских специализаций сопряжено с рядом трудностей: вероятно, придется закрыть пространства имен, в которых ведется работа и открыть пространство имен шаблона свойств iterator_traits, записать текст специализации свойств непосредственно –это не очень эффективно, по сравнению с вложенным определением типа - единственная информация, которая действительно значит что-либо.
Стандартная библиотека обеспечивает способ, который позволяет автору итератора управлять типами, вложенными в его iterator_traits только при записи типов элемента в iterator. Основной шаблон iterator_traits отыскивает iterator, чтобы захватить его типы элемента:
Стандарт C++ ссылается на обычные объявления шаблона и определения настроенный против частичных или явных (полных) специализаций основных (первичных) шаблонов.
template <class Iterator>
struct iterator_traits
{
typedef typename Iterator::value_type value_type;
//...four more typedefs
};
Это «дополнительный уровень абстракции» в работе: вместо того, чтобы идти обращаться непосредственно к Iterator::value_type, алгоритм iter_swap обращается к iterator_traits - value_type. Если некоторая специализация не переопределяет основной шаблон iterator_traits, iter_swap видит тот же самый value_type, который бы использовался во вложенном типе iterator.
Метафункции Продвижение (пересылка) метафункций
Техника использования открытого наследования базового класса для продвижения в производный класс вложенных лементов базового. (так можно продвигать множество данных по иерархии, но для этого необходимо придерживаться соглавшений о именах)
Структуры по умолчанию открыты, и их наследование тоже, причина: совместимость с языком С в котором нет инкапсуляции.
struct a{enum {_a = 1};};
struct b : a{}; // по умолчанию открытое наследование
int main()
{
cout << b::_a << endl; // применяем продвижение
return 0;
}
Класс метафункции
Расширяет понятие статического полиморфизма применяемого для свойств типов и значений, устанавливая ассоциации метеданных, используя в качетсве метаданных – вложенные в класса метафункции, что позвоялет транслировать по программе поведение, а не только состояния.
Метафункция - центральная абстракция MPL (фундаментальная единица). Это шаблонный класс, все параметры являются типами. В открытом доступе находится вложенный элемент «::type/::value», в отличии от свойств может выполнять действия.
Формат:
Имя_Метафункции<Типы параметров>
{
метафункция::type
метафункция::value
//…
};
Вызов метафункции и получение ее результата:
Имя_метафункции<аргументы>::type/::value;
Первая часть записи – вызов метафункции:
Имя_метафункции<аргументы>…
Вторая часть записи – получение результата работы метафункции:
…::type/::value;
Различие между метафункциями и классическими свойствами:
Шаблоны свойств в стандартной библиотеке все следуют модели «множественных результатов». Мы именуем этот вид шаблона свойств как «blob» ((Binary Large Object) большой двоичный объект), такие свойства подобны связке метафункций, объединенных в единый блок - эта идиома создает больше проблем, чем решений, поэтому лучше ее избегать.
Проблема эффективности:
Обращении к iterator_traits::value_type требует от компилятора много дополнительной (не нужный в данный момент) работы: помимо value_type, необходимо вычислить и четыре других связанных типа.
«блоб» вмешивается в нашу возможность записать метафункции, которые принимают другие метафункции в качестве параметров.
Рассмотрим тривиальную функцию времени выполнения, которая принимает два аргумента:
template <class X, class UnaryOp1, class UnaryOp2>
X apply_fg(X x, UnaryOp1 f, UnaryOp2 g)
{
return f(g(x));
}
Объединим f и g в единственный «блоб» параметр, т.е. в теле объекта Блоб одновременно существует 2 функции: f и g:
template <class X, class Blob>
X apply_fg(X x, Blob blob)
{
return blob.f(blob.g(x));
}
Такой вызов f и g аналогичен доступу к «блобу свойств»: чтобы получить результат «функции» необходимо обратится к одному из элементов объекта. Проблема в том, что нет единственного способа получить результат вызова одного из этих блобов или изменить извне последовательность вызовов этих функий в теле apply_fg. Каждая функция наподобии apply_fg будет использовать свой собственный набор имен функций-класса, и чтобы передать f или g другой такой функции. Решение: привнести в эту модель модульность.
«Блоб» является антипаттерном (идиома, которую избегают), потому что он уменьшает полную функциональную совместимость программы, или возможность ее компонентов работать гибко и гладко вместе.
Хорошим решением будет apply_fg, которая принимает каждую функцию в виду отдельного аргумента – это поддерживает модульность и функциональную совместимость.
Когда вызываемые параметры apply_fg используют единственный протокол, мы можем легко обмениваться ими:
#include <functional>
float log2(float);
int a = apply_fg(5.0f, std::negate<float>(), log2);
int b = apply_fg(3.14f, log2, std::negate<float>());
Правило: все, что можно разделить и сделать более независимым должно быть сделано таковым. Такая сегментированность решений – способ более эффективного конструирования, обеспечивающий большую гибкость и свободу действий, чем одно монолитное решение, которое не поддается изменениям.
Такой подход порождает полиморфизм: Свойство, которое позволяет различным типам параметра использоваться взаимозаменяемо; буквально, «возможность принимать многообразие форм.»
