- •Вычисления значений
- •Пример:
- •Вычисления типов
- •Преимущества мета подхода:
- •Польза использования mpl:
- •Числовая метафункция
- •Свойства
- •Метаданные
- •Специализация
- •Первичный шаблон:
- •Инстанцирование:
- •Метафункции
- •Полиморфизм
- •Возможности свойств:
- •Организация свойств в Boost:
- •Пример:
- •Типовые ассоциации
- •Альтернатива:
- •Метафункции Продвижение (пересылка) метафункций
- •Класс метафункции
- •Формат:
- •Числовые
- •Пример:
- •Нульарные
- •Метрический анализ (Анализ размерностей)
- •Метрики
- •Величины
- •Сложение и вычитание
- •Умножение
- •Класс метафункции
- •Деление
- •Пример:
- •Метафункции высшего порядка (Каскады вложенных вызовов)
- •Использование apply:
- •Заполнители
- •Безымянный заполнитель:
- •Определение выражений с заполнителями
- •Лямбда (Лямбда метафункции/выражения)
- •Частичное приложение метафункции
- •Лямбда и Шаблоны Неметафункции
- •Обертки
- •Выбор типа
- •Ленивый Выбор Типа
- •Логические Операторы
- •Целочисленные обертки
- •Составные Операторы
- •Операторы с булевым значением:
- •Операторы для сравнения значений:
- •Операторы для интегральных значений:
- •Побитовые операторы:
- •Арифметические операторы:
- •Целочисленная «стенография»
- •Интегральные последовательности
- •Формат:
- •Последовательности
- •Концепции
- •Итераторы
- •Двунаправленные
- •Произвольные
- •Последовательности
- •Двунаправленные
- •Произвольные
- •Расширенные
- •Ассоциативные
- •Требования
- •Расширения
- •Расширенные ассоциативные последовательности
- •Алгоритмы и последовательности
- •Итераторы
- •Равенство
- •Операции Внутренние операции с последовательностей
- •Наследование
- •Создание последовательности
- •Реализация:
- •Создание итератора
- •Преимущества полной специализации перед частичной:
- •Добавление расширения
- •Алгоритмы
- •Абстракция:
- •Stl алгоритмы
- •Детали правильного использования stl:
- •Mpl алгоритмы
- •Различия stl и mpl алгоритмов:
- •Пример:
- •Вставки
- •Пример 1:
- •Пример 2:
- •Пример 3:
- •Фундамент алгоритмов
- •Пример:
- •Запрашиваемые алгоритмы
- •Последовательности (Алгоритмы, создающие последовательности)
- •Синонимы функциональных алгоритмов:
- •Создание алгоритма
- •Итераторы «Просмотр» и итераторы-адаптеры
- •Концепция просмотра
- •Применение просмотра Сравнения значений элементов последовательности:
- •Объединение множественных (мульти-) последовательностей
- •Упрощение 1
- •Упрощение 2 (создание просмотра)
- •Уход от ненужного вычисления
- •Выборочная обработка элемента
- •Итератор-адаптер
- •Создание просмотра
- •Реализация итератора-адаптера для zip_view.
- •Диагностика
- •Отладка ошибок
- •Трассировка инстанцирования
- •Исправленный пример:
- •Форматы сообщений об ошибках
- •Блок «with»
- •Устранение параметров шаблона по умолчанию
- •Глубокий typedef
- •Инструменты
- •Несколько компиляторов
- •(Статические Утверждения)
- •Формат:
- •Формат:
- •Индивидуальные сообщения утверждений
- •Настройка предиката:
- •(Генерирование встроенных сообщений)
- •Формат:
- •Выбор стратегии:
- •Тип печати
- •Кросс этапность компиляции/выполнения
- •Печать типов:
- •Тип посещения:
- •Выбор реализаций
- •Специализация шаблонов классов
- •Тег диспетчеризации
- •Выбор структуры
- •Композиция классов
- •Указатели на функцию
- •Ослабление типизации
- •Пример:
- •Обобщение:
- •Динамический полиморфизм
- •Автоматизация
- •Сохранение интерфейса
- •Рекуррентный шаблон
- •Формат:
- •Генерирование функций
- •Управление разрешением перегрузки
- •Явное управление множеством перегрузки
- •Документация mpl Последовательности
- •Концепции
- •(Прямая последовательность)
- •(Двунаправленная Последовательность)
- •(Последовательность произвольного доступа)
- •(Расширенная последовательность)
- •(Расширенная последовательность начала)
- •(Расширенная последовательность конца)
- •(Ассоциативная последовательность)
- •(Расширенная ассоциативная последовательность)
- •(Обертка интегральной последовательности )
- •(Переменная последовательность)
- •Представления
- •Метафункции (Внутренние)
- •Итераторы
- •Концепции
- •(Прямой итератор)
- •(Двунаправленный итератор)
- •(Итератор произвольного доступа)
- •Метафункции
- •Алгоритмы
- •Концепции
- •(Инсертер: механизм вставок)
- •Инсертеры (инсертер: механизм вставок)
- •Итеративные алгоритмы
- •Запрашиваемые алгоритмы
- •Преобразования
- •Метафункции
- •Концепции Метафункция
- •Метафункциональный класс
- •Лямбда выражения
- •Заполнители
- •Тэг диспетчеризированные метафункции
- •Числовые метафункции
- •Тривиальные метафункции
Кросс этапность компиляции/выполнения
for_each
Алгоритм std::for_each имеет своего аналога в MPL, который работает подобным образом. Так, std:: for_each делает обход (во время выполнения) всех элементов последовательности, вызывает некоторые функторы (времени выполнения) для каждого элемента. Алгоритм mpl::for_each делает обход (во время компиляции) всех элементов последовательности, вызывает некоторые функторы (времени выполнения)для каждого элемента. Хотя std::for_each работает только во время выполнения, mpl:: for_each представляет собой гибрид, поддерживающий кросс-этапность своего выполнения.
Причина, по которой mpl:: for_each использует функторы времени выполнения, вместо метафункций: как правило, функторы, использующиеся в std:: for_each имеют тип возвращаемого значения void, но даже, если возвращаемое значение есть, то оно не учитывается. Т.о. цель функтора в алгоритме for_each –приводить к изменению состояний. Поскольку функциональное программирование по своей сути не имеет состояний, а шаблонные метапрограммы являются функциональными, то нет особого смысла в вызове метафункций, для каждого элемента последовательности, если с этими результатами ничего нельзя сделать.
Печать типов:
При использовании механизмов type_info можно распечатать каждый элемент последовательности типов следующим образом:
struct print_type
{
template <class T>
void operator()(T) const
{
std::cout << typeid(T).name() << std::endl;
}
};
typedef mpl::vector<int, long, char*> s;
int main()
{
mpl::for_each<s>(print_type());
return 0;
}
Оператор вызова функций в теле print_type является шаблонным, потому что он должен обрабатывать любой тип, который находится в последовательности. Если в последовательности представлены типы, которые могут быть преобразованы к одному типу или, если, для каждого типа в списке есть перегруженная функция, то оператор вызова не обязан быть шаблонным для использования mpl::for_each.
Алгоритм for_each передает каждый элемент последовательности как значение для инициализации объекта соответствующего типа элемента. Эта форма особенно удобна для осуществления итераций по последовательности интегральных константных оберток, которые неявно преобразовываются в соответствующие константы времени выполнения. При работе с обычной последовательностью типов требуется некоторая осторожность: если элемент оказывается ссылочным типом, классом без конструктора по умолчанию, или просто типом void, то для этих типов алгоритм не сможет выполнить инициализацию объекта значением, что приведет к сбою.
Инициализация объекта значением – сопоставление шаблонного типа Т с переданным типом из списка. Для инициализации значением типа Т, необходимо выполнение следующих требований:
Если T является типом класса, который содержить хотя бы 1 конструктор (не по умолчанию), то обязательно, в теле класса, должен быть явно объявлен конструктор по умолчанию.
Если Т не является объединением и не содержит объявленных пользователем конструкторов, то каждый нестатический элемент данных и элементы его базового класса типа Т могут быть инициализированы значением.
Если T является типом массива, то для каждого элемента выполняется инициализация значением.
В противном случае, объект не будет инициализирован.
Можно избежать некоторые проблемные места, прмиеняя специальные шаблонные обертки:
template <class T>
struct wrap{};
// contains references
typedef mpl::vector<int&, long&, char*&> s; // !"*&"
mpl::for_each<
mpl::transform<s, wrap<_1> // поместит все типы в обертки.
>::type>(print_type());
Нюанс: ссылка на указатель «*&» допускается, что приведет к ведению работы с оригиналом указателя, но указатель на ссылку «&*» недопустим. Предотвратить возможное появление указателя на ссылку можно использованием свойств.
Необходимо изменить также сигнатуру функтора , от которой зависит вывод типов передаваемых аргументов:
struct print_type
{
template <class T>
void operator()(wrap<T>) const // deduce T
{
std::cout << typeid(T).name() << std::endl;
}
};
Для поддержки этой идиомы, MPL предоставляет вторую форму алгоритма mpl::far_each, который принимает метафункции преобразования в качестве дополнительного аргумента шаблона, что позвоялет избежать явного создания новой последовательности:
mpl::for_each<s, wrap<_1>>(print_type());
Каждый элемент Т последовательности s , будет передан функтору print_type в качестве аргумента типа warp<T>.
